【UGUI】屏幕区域点击检测

来源:互联网 发布:淘宝上的原创女装品牌 编辑:程序博客网 时间:2024/05/19 10:09

此处直接代码:

using System.Collections;using System.Collections.Generic;using UnityEngine;namespace Asstes.UI{    /// <summary>    /// Introduction: 屏幕区域点击判断    /// Author:     /// Time:     /// </summary>    public class AreaClick    {        private static AreaClick m_instance;        public static AreaClick Instance        {            get            {                if (m_instance == null)                    m_instance = new AreaClick();                return m_instance;            }        }        private int m_index;        private List<AreaRect> m_rects;        private List<AreaRect> m_removes;        private List<int> m_deletes;        public AreaClick()        {            m_index = 0;            m_rects = new List<AreaRect>();            m_removes = new List<AreaRect>();            m_deletes = new List<int>();            InputManager.Instance.AddListener(InputType.OnClick, OnClickScreen);            InputManager.Instance.AddListener(InputType.OnEndLongPress, OnClickScreen);        }        private void OnClickScreen(Vector2 param)        {            m_removes.Clear();            for (int i = 0; i < m_rects.Count; i++)//移除已删除的点            {                if(m_deletes.Contains(m_rects[i].id))                    m_removes.Add(m_rects[i]);            }            for (int i = 0; i < m_removes.Count; i++)            {                m_rects.Remove(m_removes[i]);            }            m_deletes.Clear();            for (int i = 0; i < m_rects.Count; i++)            {                m_rects[i].OnClick(param);            }        }        /// <summary>        /// 添加检测        /// </summary>        /// <param name="area"></param>        /// <returns></returns>        public int AddCheck(AreaRect area)        {            area.id = m_index++;            m_rects.Add(area);            return area.id;        }        /// <summary>        /// 移除检测        /// </summary>        /// <param name="id"></param>        public void CancelCheck(int id)        {            if(!m_deletes.Contains(id))                m_deletes.Add(id);        }    }    public class AreaRect    {        private Rect m_rect;        private bool m_allNotice;        private bool m_onlyOnce;        private Callback_1<bool> m_callback;        internal int id;        /// <summary>        /// 是否只使用一次        /// </summary>        public bool UseOnce { get { return m_onlyOnce; } set { m_onlyOnce = value; } }        /// <summary>        /// 普通构造函数        /// </summary>        /// <param name="rect">在屏幕上的区域</param>        /// <param name="allNotice">通知点中和未点中</param>        /// <param name="callback">回调</param>        public AreaRect(Rect rect, bool allNotice, Callback_1<bool> callback)        {            m_rect = rect;            m_allNotice = allNotice;            m_callback = callback;        }        /// <summary>        /// 可缩放区域        /// </summary>        /// <param name="rect">设计时所选区域,如UI设计时的rect</param>        /// <param name="designSize">UI设计时屏幕分辨率</param>        /// <param name="allNotice">通知点中和未点中</param>        /// <param name="callback">回调</param>        public AreaRect(Rect rect, Vector2 designSize, bool allNotice, Callback_1<bool> callback)        {            float sx = Screen.width/designSize.x;            float sy = Screen.height/designSize.y;            Rect newRect = new Rect()            {                x = rect.x*sx,                y = rect.y*sy,                width = rect.width*sx,                height = rect.height*sy            };            m_rect = newRect;            m_allNotice = allNotice;            m_callback = callback;        }        /// <summary>        /// UI区域        /// </summary>        /// <param name="transform">RectTransform</param>        /// <param name="allNotice">通知点中和未点中</param>        /// <param name="callback">回调</param>        public AreaRect(Transform transform, bool allNotice, Callback_1<bool> callback)        {            RectTransform rectTransform = transform as RectTransform;            /*m_rect = rectTransform.rect; //没有考虑到缩放问题,当缩放后rect的长宽并未改变            m_rect.center = rectTransform.position;*/ //没有考虑到中心点影响,center并非world position            float w = rectTransform.sizeDelta.x * rectTransform.lossyScale.x;//消除缩放影响            float h = rectTransform.sizeDelta.y * rectTransform.localScale.y;            float x = rectTransform.position.x - rectTransform.pivot.x * w; //消除中心点并非pivot非(0.5,0.5)影响            float y = rectTransform.position.y - rectTransform.pivot.y * h;            m_rect.center = new Vector2(x, y);            m_rect.width = w;            m_rect.height = h;            m_allNotice = allNotice;            m_callback = callback;        }        /// <summary>        /// 是否在区域中        /// </summary>        /// <param name="pos"></param>        /// <returns></returns>        public bool IsContain(Vector3 pos)        {            return m_rect.Contains(pos);        }        public void OnClick(Vector2 pos)        {            if (IsContain(pos))            {                m_callback(true);                if(m_onlyOnce)                    AreaClick.Instance.CancelCheck(id);            }            else if(m_allNotice)            {                m_callback(false);            }        }    }}


其中InputManager是我自己实现的一个在多平台上判断点击事件的工具,

InputManager.Instance.AddListener(InputType.OnClick, OnClickScreen);InputManager.Instance.AddListener(InputType.OnEndLongPress, OnClickScreen);
可直接用

Input.GetMouseButtonDown(0) 和Input.GetTouch(0)***************代替判断

一个很平常的需求、点击空白处关闭界面,以前自己的做法是给它做个全透明的图片托底(当时自己也没有想其他方法),当判断到点击是图片后关闭。但最近时遇到一个不能用这个方法的,因为你不能遮住其他的UI点击事件,故写了个工具,并做了个小扩展,目前只支持矩形区域的硬检测。目前可用到所有的屏幕区域检测和RectTransform检测。



由于最近用到在拖动时,如果在某个区域则相应拖动事件,如果超过这个区域则停止移动,于是改了一下代码:

using System.Collections;using System.Collections.Generic;using UnityEngine;namespace Assets.UI{    /// <summary>    /// Introduction: 屏幕区域点击移动判断    /// Author:         Cheng    /// Time:     /// </summary>    public class AreaCheck    {        private static AreaCheck m_instance;        public static AreaCheck Instance        {            get            {                if (m_instance == null)                    m_instance = new AreaCheck();                return m_instance;            }        }        private int m_index;        private List<AreaRect> m_rects;        private List<AreaRect> m_removes;        private List<int> m_deletes;        public AreaCheck()        {            m_index = 0;            m_rects = new List<AreaRect>();            m_removes = new List<AreaRect>();            m_deletes = new List<int>();            InputManager.Instance.AddListener(InputType.OnTouchBegin, OnTouchBegin);            InputManager.Instance.AddListener(InputType.OnMoveBegin, OnMoveBrgin);            InputManager.Instance.AddListener(InputType.OnMove, OnMove);            InputManager.Instance.AddListener(InputType.OnMoveEnd, OnMoveEnd);            InputManager.Instance.AddListener(InputType.OnClick, OnClickScreen);            InputManager.Instance.AddListener(InputType.OnEndLongPress, OnClickScreen);        }        private void OnTouchBegin(Vector2 param)        {            m_removes.Clear();            for (int i = 0; i < m_rects.Count; i++)//移除已删除的点            {                if (m_deletes.Contains(m_rects[i].id))                    m_removes.Add(m_rects[i]);            }            for (int i = 0; i < m_removes.Count; i++)            {                m_rects.Remove(m_removes[i]);            }            m_deletes.Clear();        }        private void OnClickScreen(Vector2 param)        {            for (int i = 0; i < m_rects.Count; i++)            {                m_rects[i].OnClick(param);            }        }        private void OnMoveBrgin(Vector2 param)        {            for (int i = 0; i < m_rects.Count; i++)            {                m_rects[i].OnMoveBegin(param);            }        }        private void OnMove(Vector2 param)        {            for (int i = 0; i < m_rects.Count; i++)            {                m_rects[i].OnMove(param);            }        }        private void OnMoveEnd(Vector2 param)        {            for (int i = 0; i < m_rects.Count; i++)            {                m_rects[i].OnMoveEnd(param);            }        }        /**********因lua重载的callback只检测luafunction,改重载为重命名  T_T  ************************/        public int AddClickCheckRect(Rect rect, bool noticeAll, Callback_1<bool> callback)        {            AreaRect area = new AreaRect(rect)            {                CheckClick = true,                ClickAllNotice = noticeAll,                ClickCallback = callback            };            return AddCheck(area);        }        public int AddClickCheckResizeRect(Rect rect, Vector2 designSize, bool noticeAll, Callback_1<bool> callback)        {            AreaRect area = new AreaRect(rect, designSize)            {                CheckClick = true,                ClickAllNotice = noticeAll,                ClickCallback = callback            };            return AddCheck(area);        }        public int AddClickCheckTransform(Transform transform, bool noticeAll, Callback_1<bool> callback)        {            AreaRect area = new AreaRect(transform)            {                CheckClick = true,                ClickAllNotice = noticeAll,                ClickCallback = callback            };            return AddCheck(area);        }        public int AddMoveCheckRect(Rect rect, bool outOnEnd, Callback_1<Vector2> begin, Callback_1<Vector2> move, Callback_1<Vector2> end)        {            AreaRect area = new AreaRect(rect)            {                CheckMove = true,                EndOnOut = outOnEnd,                MoveBeginCallback = begin,                MoveCallback = move,                MoveEndCallback = end            };            return AddCheck(area);        }        public int AddMoveCheckResizeRect(Rect rect, Vector2 designSize, bool outOnEnd, Callback_1<Vector2> begin, Callback_1<Vector2> move, Callback_1<Vector2> end)        {            AreaRect area = new AreaRect(rect, designSize)            {                CheckMove = true,                EndOnOut = outOnEnd,                MoveBeginCallback = begin,                MoveCallback = move,                MoveEndCallback = end            };            return AddCheck(area);        }        public int AddMoveCheckTransform(Transform transform, bool outOnEnd, Callback_1<Vector2> begin, Callback_1<Vector2> move, Callback_1<Vector2> end)        {            AreaRect area = new AreaRect(transform)            {                CheckMove = true,                EndOnOut = outOnEnd,                MoveBeginCallback = begin,                MoveCallback = move,                MoveEndCallback = end            };            return AddCheck(area);        }        /// <summary>        /// 添加检测        /// </summary>        /// <param name="area"></param>        /// <returns></returns>        [LuaInterface.NoToLua]        public int AddCheck(AreaRect area)        {            area.id = m_index++;            m_rects.Add(area);            return area.id;        }        /// <summary>        /// 移除检测        /// </summary>        /// <param name="id"></param>        public void CancelCheck(int id)        {            if(!m_deletes.Contains(id))                m_deletes.Add(id);        }    }    public class AreaRect    {        private Rect m_rect;        private bool moving;        internal int id;        /// <summary>        /// 鼠标移动时移除即结束        /// </summary>        public bool EndOnOut{ get; set; }        /// <summary>        /// 通知点中和未点中        /// </summary>        public bool ClickAllNotice { get; set; }        /// <summary>        /// 检测点击        /// </summary>        public bool CheckClick { get; set; }        /// <summary>        /// 检测移动        /// </summary>        public bool CheckMove { get; set; }        /// <summary>        /// 点击回调        /// </summary>        public Callback_1<bool> ClickCallback;        /// <summary>        /// 移动结束回调        /// </summary>        public Callback_1<Vector2> MoveBeginCallback;        /// <summary>        /// 移动回调        /// </summary>        public Callback_1<Vector2> MoveCallback;        /// <summary>        /// 移动结束回调        /// </summary>        public Callback_1<Vector2> MoveEndCallback;        /// <summary>        /// 普通构造函数        /// </summary>        /// <param name="rect">在屏幕上的区域</param>        public AreaRect(Rect rect)        {            m_rect = rect;        }        /// <summary>        /// 可缩放区域        /// </summary>        /// <param name="rect">设计时所选区域,如UI设计时的rect</param>        /// <param name="designSize">UI设计时屏幕分辨率</param>        public AreaRect(Rect rect, Vector2 designSize)        {            float sx = Screen.width/designSize.x;            float sy = Screen.height/designSize.y;            Rect newRect = new Rect()            {                x = rect.x*sx,                y = rect.y*sy,                width = rect.width*sx,                height = rect.height*sy            };            m_rect = newRect;        }        /// <summary>        /// UI区域        /// </summary>        /// <param name="transform">RectTransform</param>        public AreaRect(Transform transform)        {            RectTransform rectTransform = transform as RectTransform;            /*m_rect = rectTransform.rect; //没有考虑到缩放问题,当缩放后rect的长宽并未改变            m_rect.center = rectTransform.position;*/ //没有考虑到中心点影响,center并非world position            float w = rectTransform.sizeDelta.x * rectTransform.lossyScale.x;//消除缩放影响            float h = rectTransform.sizeDelta.y * rectTransform.localScale.y;            float x = rectTransform.position.x - rectTransform.pivot.x * w; //消除中心点并非pivot非(0.5,0.5)影响            float y = rectTransform.position.y - rectTransform.pivot.y * h;            m_rect.center = new Vector2(x, y);            m_rect.width = w;            m_rect.height = h;        }        /// <summary>        /// 是否在区域中        /// </summary>        /// <param name="pos"></param>        /// <returns></returns>        public bool IsContain(Vector3 pos)        {            return m_rect.Contains(pos);        }        /// <summary>        /// 区域点击检测        /// </summary>        /// <param name="pos"></param>        public void OnClick(Vector2 pos)        {            if(!CheckClick) return;            if (IsContain(pos) && ClickCallback != null)            {                ClickCallback(true);            }            else if (ClickAllNotice && ClickCallback != null)            {                ClickCallback(false);            }        }        /// <summary>        /// 开始移动        /// </summary>        /// <param name="pos"></param>        public void OnMoveBegin(Vector2 pos)        {            if (!CheckMove) return;            if (IsContain(pos))            {                moving = true;                if (MoveBeginCallback != null)                    MoveBeginCallback(pos);            }        }        /// <summary>        /// 区域移动检测        /// </summary>        /// <param name="pos"></param>        public void OnMove(Vector2 pos)        {            if(!moving || !CheckMove) return;            if (IsContain(pos))            {                if (MoveCallback != null)                    MoveCallback(pos);            }            else            {                if (EndOnOut)                {                    moving = false;                    if (MoveEndCallback != null)                        MoveEndCallback(pos);                }                else                {                    if (MoveCallback != null)                        MoveCallback(pos);                }            }        }        /// <summary>        /// 移动结束        /// </summary>        /// <param name="pos"></param>        public void OnMoveEnd(Vector2 pos)        {            if (!moving || !CheckMove) return;            if (MoveEndCallback != null)                MoveEndCallback(pos);        }    }}


使用方式现在直接调用AreaCheck的单例即可。

2 0