Unity杂文——UI点击穿透

  1. 简介
  2. 代码

Unity3D研究院之UI完整透下事件(一百二十二)——雨松MOMO

简介

当UI打开一个小的提示tip的时候,常见的需求是点击其他任意地方就关闭tip,这个功能很常见,空白出响应点击,监听到就关闭tip,这里会发现一个问题,我们并不能响应tip面板底下的其他按钮,这样玩家在操作的时候就需要先关掉tip,然后再点一下按钮,这往往不是策划想要的,所以我们需要在点击空白处关闭的时候同时响应底下的按钮,这个时候就需要点击穿透事件。

代码

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

namespace ZHEngine.UI
{
    public sealed class UTouchPass : MonoBehaviour, IPointerClickHandler,
    IMoveHandler,IPointerDownHandler, IPointerUpHandler,IPointerEnterHandler,ISelectHandler, IDeselectHandler
    , ISubmitHandler, IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler, IDragHandler, IScrollHandler
    {
        private GameObject CacheGameObject;
        private readonly List<RaycastResult> result = new List<RaycastResult>();

        public void OnPointerClick(PointerEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.pointerClickHandler);
        }
        public void OnPointerDown(PointerEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.pointerDownHandler);
            if (Input.GetButtonDown("Submit"))
               ExecuteEvents.Execute(eventData.pointerCurrentRaycast.gameObject, eventData, ExecuteEvents.submitHandler);
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.pointerUpHandler);
        }

        public void OnPointerEnter(PointerEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.pointerEnterHandler);
        }

        public void OnSelect(BaseEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.selectHandler);
        }

        public void OnDeselect(BaseEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.deselectHandler);
        }

        public void OnSubmit(BaseEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.submitHandler);
        }

        public void OnMove(AxisEventData eventData)
        {
            PassEvent(eventData, ExecuteEvents.moveHandler);
        }
        public void OnInitializePotentialDrag(PointerEventData eventData)
        {
            CacheGameObject = PassEvent(eventData, ExecuteEvents.initializePotentialDrag);
        }
        public void OnBeginDrag(PointerEventData eventData)
        {
             PassEvent(eventData, ExecuteEvents.beginDragHandler);
        }
        public void OnDrag(PointerEventData eventData)
        {
            ExecuteEvents.Execute(CacheGameObject, eventData, ExecuteEvents.dragHandler);
        }
        public void OnEndDrag(PointerEventData eventData)
        {
            ExecuteEvents.Execute(CacheGameObject, eventData, ExecuteEvents.endDragHandler);
            CacheGameObject = null;
        }
        public void OnScroll(PointerEventData eventData)
        {
            ExecuteEvents.Execute(CacheGameObject, eventData, ExecuteEvents.scrollHandler);
        }

        private GameObject PassEvent<T>(BaseEventData data, ExecuteEvents.EventFunction<T> function) where T : IEventSystemHandler
        {
            if (data is PointerEventData eventData)
            {
                var pointerGo = eventData.pointerCurrentRaycast.gameObject
                    ? eventData.pointerCurrentRaycast.gameObject
                    : eventData.pointerDrag;
                EventSystem.current.RaycastAll(eventData, result);
                foreach (var item in result)
                {
                    var go = item.gameObject;
                    if (go != null && go != pointerGo)
                    {
                        var executeGo = ExecuteEvents.GetEventHandler<T>(go);
                        if (executeGo)
                        {
                            if (executeGo.TryGetComponent<UTouchPass>(out var __))
                                return null;
                            ExecuteEvents.Execute(executeGo, data, function);
                            return executeGo;
                        }
                        else
                        {
                            if(go.TryGetComponent<UnityEngine.UI.Graphic>(out var com))
                            {
                                if (com.raycastTarget) return null;
                            }
                        }
                    }
                }
            }

            return null;
        }
    }
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 841774407@qq.com

×

喜欢就点赞,疼爱就打赏