首页 >Unity3D频道 >【Unity3D研究院之游戏开发】 > Unity3D研究院之UI完整透下事件(一百二十二)
2020
12-28

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

以前写过一篇类似的文章用于解决新手引导的问题,  Unity3D研究院之将UI的点击事件渗透下去(九十)  最近策划又提出一个需求,Tips窗口打开以后点击空白区域关掉,但是如果空白区域下有按钮滑动输入一类的要关掉Tips的同时要响应相面的事件,所以透下的事件就要比较完整了。开始我觉得这个需求很不合理,但是他们给我找了个这样实现的游戏,我瞬间只能服了。

8b0d88d5ly1gl775ckmbxg20ci0cijui

8b0d88d5ly1gl775i00urj208w078wev

8b0d88d5ly1gl775jt6ygj20kq0ggabi

 

代码在项目中已经测试了一段时间了,同时也欢迎大家测试。

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

public class UITouchPass : MonoBehaviour, IPointerClickHandler,
    IMoveHandler,IPointerDownHandler, IPointerUpHandler,IPointerEnterHandler,ISelectHandler, IDeselectHandler
    , ISubmitHandler, IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler, IDragHandler, IScrollHandler
{
    public virtual void OnPointerClick(PointerEventData eventData)
    {
        PassEvent(eventData, ExecuteEvents.pointerClickHandler);
    }
    public virtual void OnPointerDown(PointerEventData eventData)
    {
        PassEvent(eventData, ExecuteEvents.pointerDownHandler);
        if (Input.GetButtonDown("Submit"))
           ExecuteEvents.Execute(eventData.pointerCurrentRaycast.gameObject, eventData, ExecuteEvents.submitHandler);
    }

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

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

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

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

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

    public virtual void OnMove(AxisEventData eventData)
    {
        PassEvent(eventData, ExecuteEvents.moveHandler);
    }

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

    List<RaycastResult> result = new List<RaycastResult>();
    GameObject PassEvent<T>(BaseEventData data, ExecuteEvents.EventFunction<T> function) where T : IEventSystemHandler
    {
        PointerEventData eventData = data as PointerEventData;
        var pointerGo = 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 excuteGo = ExecuteEvents.GetEventHandler<T>(go);
                if (excuteGo)
                {
                    if (excuteGo.TryGetComponent<UITouchPass>(out var __))
                        return null;
                    ExecuteEvents.Execute(excuteGo, data, function);
                    return excuteGo;
                }
                else
                {
                    if(go.TryGetComponent<UnityEngine.UI.Graphic>(out var com))
                    {
                        if (com.raycastTarget) return null;
                    }
                }
            }
        }
        return null;
    }
}

 

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之UI完整透下事件(一百二十二)》有 12 条评论

  1. 东山说:

    我一般做法tips后面一个透明ui很大,可以点击关闭,但是识别滚动关闭就不行了,这个需求太变态了。

  2. skyAllen说:

    这种需求,一定要回怼,就算有游戏实现了就一定就是好的吗?时间要花在刀刃上,如果什么需求都听策划,绝对不是一个好的程序员,程序员做不到聪明地偷懒,浪费大把时间在产出比低的事情上,其个人的价值是无法最大化的。甚至只能在当一辈子打工人,逃不出这仓鼠滚轮游戏

  3. U3D好难说:

    我遇到一个问题,如果下面是摇杆,然后拖动操作滑出摇杆范围,OnPointerUp和OnEndDrag就没法穿透下去,或者说找不到正确的接收者

  4. Vae说:

    大佬,我像问下不同Canvas下的组件可以互相渗透嘛?

  5. 我要米饭说:

    如果一个穿透按钮下面子物体图片了响应了穿透事件,那会不会无限循环触发导致堆栈溢出

  6. shpkng说:

    我之前的项目里也有这样的需求,不过我是通过增加一个全局的点击监听来实现的,监听到PointerDown事件的时候检查是否在自身UI的Rect中,这样可以不用魔改EventSystem

  7. 超~~说:

    哈哈,我的滑动列表里有button,在滑动结束的时候会触发button的点击

  8. Fly说:

    哈哈 遇到这个需求太正常了,以前都是直接在Update之类的检测点击,然后判断一下点击的东西是否自己,不是就关掉

留下一个回复

你的email不会被公开。 必填项已用 * 标注。