Unity-鼠标监测UI事件

Unity-鼠标监测UI事件

最近开发项目中碰到的问题,需要实时监测鼠标是否进入、离开、点击UI区域,查了一些资料,总结了一些经验,写下这篇笔记,希望能够给碰到相同问题的同仁提供一些帮助

使用UGUI的GraphicRaycaster.Raycast方法进行检测鼠标位置,首先需要一个UI事件的管理类,代码如下:
使用事件字典每一个UI物体的同一种事件可以注册多个委托,只需要往MouseEventMgr中注册事件就行了:AddListener_…
当需要移除掉某一个事件时以RemoveListener_…即可
这个事件管理类随便挂在场景中的任意一个空物体即可

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class MouseEventMgr : MonoBehaviour
{
    private GraphicRaycaster gra;

    public delegate void EventUI(Transform target);

    //鼠标点击UI事件字典
    static Dictionary> mouseDownEvents = new Dictionary>();

    //鼠标释放UI事件字典
    static Dictionary> mouseUpEvents = new Dictionary>();
    
    //鼠标进入UI事件字典
    static Dictionary> mouseEnterEvents = new Dictionary>();

    //鼠标离开UI事件字典
    static Dictionary> mouseExitEvents = new Dictionary>();
    
    //鼠标悬停UI事件字典
    static Dictionary> mouseStayEvents = new Dictionary>();

    private bool isCheck {
        get {
            return (mouseDownEvents.Count != 0 && mouseUpEvents.Count != 0 && mouseEnterEvents.Count != 0 && mouseExitEvents.Count != 0 && mouseStayEvents.Count != 0);
        }
    }

    private void Awake()
    {
        gra = GameObject.Find("Canvas").GetComponent();
    }

    #region 事件管理

    /// 
    /// 给鼠标点击UI添加事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void AddListener_MouseDown(Transform target,EventUI eventUI) {
        if (mouseDownEvents.ContainsKey(target))
        {
            mouseDownEvents[target].Add(eventUI);
        }
        else {
            List list = new List();
            list.Add(eventUI);
            mouseDownEvents.Add(target,list);
        }
    }

    /// 
    /// 给鼠标点击UI移除事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void RemoveListener_MouseDown(Transform target, EventUI eventUI) {
        if (mouseDownEvents.ContainsKey(target))
        {
            try
            {
                mouseDownEvents[target].Remove(eventUI);
                if (mouseDownEvents[target].Count==0)
                {
                    mouseDownEvents.Remove(target);
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError("RemoveListener_MouseDown Error:"+ex.ToString());
            }
        }
    }

    /// 
    /// 给鼠标释放UI添加事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void AddListener_MouseUp(Transform target, EventUI eventUI)
    {
        if (mouseUpEvents.ContainsKey(target))
        {
            mouseUpEvents[target].Add(eventUI);
        }
        else
        {
            List list = new List();
            list.Add(eventUI);
            mouseUpEvents.Add(target, list);
        }
    }

    /// 
    /// 给鼠标释放UI移除事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void RemoveListener_MouseUp(Transform target, EventUI eventUI)
    {
        if (mouseUpEvents.ContainsKey(target))
        {
            try
            {
                mouseUpEvents[target].Remove(eventUI);
                if (mouseUpEvents[target].Count == 0)
                {
                    mouseUpEvents.Remove(target);
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError("RemoveListener_MouseUp Error:" + ex.ToString());
            }
        }
    }

    /// 
    /// 给鼠标悬停UI添加事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void AddListener_MouseStay(Transform target, EventUI eventUI)
    {
        if (mouseStayEvents.ContainsKey(target))
        {
            mouseStayEvents[target].Add(eventUI);
        }
        else
        {
            List list = new List();
            list.Add(eventUI);
            mouseStayEvents.Add(target, list);
        }
    }

    /// 
    /// 给鼠标悬停UI移除事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void RemoveListener_MouseStay(Transform target, EventUI eventUI)
    {
        if (mouseStayEvents.ContainsKey(target))
        {
            try
            {
                mouseStayEvents[target].Remove(eventUI);
                if (mouseStayEvents[target].Count == 0)
                {
                    mouseStayEvents.Remove(target);
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError("RemoveListener_MouseStay Error:" + ex.ToString());
            }
        }
    }

    /// 
    /// 给鼠标进入UI添加事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void AddListener_MouseEnter(Transform target, EventUI eventUI)
    {
        if (mouseEnterEvents.ContainsKey(target))
        {
            mouseEnterEvents[target].Add(eventUI);
        }
        else
        {
            List list = new List();
            list.Add(eventUI);
            mouseEnterEvents.Add(target, list);
        }
    }

    /// 
    /// 给鼠标进入UI移除事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void RemoveListener_MouseEnter(Transform target, EventUI eventUI)
    {
        if (mouseEnterEvents.ContainsKey(target))
        {
            try
            {
                mouseEnterEvents[target].Remove(eventUI);
                if (mouseEnterEvents[target].Count == 0)
                {
                    mouseEnterEvents.Remove(target);
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError("RemoveListener_MouseEnter Error:" + ex.ToString());
            }
        }
    }

    /// 
    /// 给鼠标离开UI添加事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void AddListener_MouseExit(Transform target, EventUI eventUI)
    {
        if (mouseExitEvents.ContainsKey(target))
        {
            mouseExitEvents[target].Add(eventUI);
        }
        else
        {
            List list = new List();
            list.Add(eventUI);
            mouseExitEvents.Add(target, list);
        }
    }

    /// 
    /// 给鼠标离开UI移除事件
    /// 
    /// 目标UI
    /// 响应事件
    public static void RemoveListener_MouseExit(Transform target, EventUI eventUI)
    {
        if (mouseExitEvents.ContainsKey(target))
        {
            try
            {
                mouseExitEvents[target].Remove(eventUI);
                if (mouseExitEvents[target].Count == 0)
                {
                    mouseExitEvents.Remove(target);
                }
            }
            catch (System.Exception ex)
            {
                Debug.LogError("RemoveListener_MouseExit Error:" + ex.ToString());
            }
        }
    }

    #endregion

    /// 
    /// 触发目标事件
    /// 
    /// 目标类型
    /// 事件管理字典
    /// 目标
    /// 事件参数
    public void UseMouseEvent(Dictionary> dict,T key,Transform value) {
        if (dict==null||!dict.ContainsKey(key))
        {
            return;
        }
        List events = dict[key];
        for (int i = 0; i < events.Count; i++)
        {
            events[i]?.Invoke(value);
        }
    }


    List lastList = null;
    void Update()
    {
        if (!isCheck)
        {
            return;
        }
        PointerEventData pd = new PointerEventData(EventSystem.current);
        pd.position = Input.mousePosition;
        List list = new List();
        gra.Raycast(pd, list);
        if (mouseExitEvents.Count != 0 &&lastList!=null&&lastList.Count != 0)
        {
            CheckExit(list);
        }
        
        for (int i = 0; i < list.Count; i++)
        {
            Transform trans = list[i].gameObject.transform;
            if (mouseEnterEvents.Count != 0)
            {
                if (!ListExist(lastList,list[i])&&mouseEnterEvents.ContainsKey(trans))
                {
                    UseMouseEvent(mouseEnterEvents,trans,trans);
                }
            }
            if (mouseStayEvents.ContainsKey(trans))
            {
                UseMouseEvent(mouseStayEvents,trans,trans);
            }
            if (Input.GetMouseButtonDown(0))
            {
                UseMouseEvent(mouseDownEvents, trans, trans);
            }
            else if (Input.GetMouseButtonUp(0))
            {
                UseMouseEvent(mouseUpEvents, trans, trans);
            }
        }
        lastList = list;
    }

    //监测离开事件
    void CheckExit(List curList) {
        List exitList = GetExitObjs(curList);
        for (int i = 0; i < exitList.Count; i++)
        {
            Transform exitObj = exitList[i].gameObject.transform;
            if (mouseExitEvents.ContainsKey(exitObj))
            {
                UseMouseEvent(mouseExitEvents, exitObj, exitObj);
            }
        }
    }
    
    //得到所有鼠标离开的UI
    List GetExitObjs(List curList) {
        List exitList = new List();
        for (int i = 0; i < lastList.Count; i++)
        {
            RaycastResult result = lastList[i];
            if (!ListExist(curList,result))
            {
                exitList.Add(result);
            }
        }
        return exitList;
    }
    

    //列表中是否包含指定元素
    bool ListExist(List list, RaycastResult t) {
        if (list==null||list.Count==0)
        {
            return false;
        }
        for (int i = 0; i < list.Count; i++)
        {
            if (list[i].gameObject==t.gameObject)
            {
                return true;
            }
        }
        return false;
    }
    

}


下面开始注册UI事件并处理事件逻辑,代码如下:


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UIMgr : MonoBehaviour
{
    public Transform[] mouseDownObjs;//需要处理鼠标点击的UI物体
    public Transform[] mouseUpObjs;//需要处理鼠标释放的UI物体
    public Transform[] mouseStayObjs;//需要处理鼠标悬停的UI物体
    public Transform[] mouseExitObjs;//需要处理鼠标离开的UI物体
    public Transform[] mouseEnterObjs;//需要处理鼠标进入的UI物体


    void Start()
    {
        AddListener();
    }

    void AddListener() {
        for (int i = 0; i < mouseDownObjs.Length; i++)
        {
            Transform obj = mouseDownObjs[i];
            MouseEventMgr.AddListener_MouseDown(obj,MouseDown);
        }
        for (int i = 0; i < mouseUpObjs.Length; i++)
        {
            Transform obj = mouseUpObjs[i];
            MouseEventMgr.AddListener_MouseUp(obj, MouseUp);
        }
        for (int i = 0; i < mouseStayObjs.Length; i++)
        {
            Transform obj = mouseStayObjs[i];
            MouseEventMgr.AddListener_MouseStay(obj, MouseStay);
        }
        for (int i = 0; i < mouseExitObjs.Length; i++)
        {
            Transform obj = mouseExitObjs[i];
            MouseEventMgr.AddListener_MouseExit(obj, MouseExit);
        }
        for (int i = 0; i < mouseEnterObjs.Length; i++)
        {
            Transform obj = mouseEnterObjs[i];
            MouseEventMgr.AddListener_MouseEnter(obj, MouseEnter);
        }
    }


    public void MouseDown(Transform obj)
    {
        Debug.Log("鼠标点击到UI物体:"+obj.name);
    }
    
    public void MouseUp(Transform obj)
    {
        Debug.Log("鼠标释放到UI物体:" + obj.name);
    }

    public void MouseStay(Transform obj)
    {
        Debug.Log("鼠标悬停到UI物体:" + obj.name);
    }

    public void MouseExit(Transform obj)
    {
        Debug.Log("鼠标离开UI物体:" + obj.name);
    }
    public void MouseEnter(Transform obj)
    {
        Debug.Log("鼠标进入UI物体:" + obj.name);
    }
}


你可能感兴趣的:(Unity,c#)