以前写过一篇类似的文章用于解决新手引导的问题, Unity3D研究院之将UI的点击事件渗透下去(九十) 最近策划又提出一个需求,Tips窗口打开以后点击空白区域关掉,但是如果空白区域下有按钮滑动输入一类的要关掉Tips的同时要响应相面的事件,所以透下的事件就要比较完整了。开始我觉得这个需求很不合理,但是他们给我找了个这样实现的游戏,我瞬间只能服了。
代码在项目中已经测试了一段时间了,同时也欢迎大家测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
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; } } |
- 本文固定链接: https://www.xuanyusong.com/archives/4773
- 转载请注明: 雨松MOMO 于 雨松MOMO程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!
这种需求,一定要回怼,就算有游戏实现了就一定就是好的吗?时间要花在刀刃上,如果什么需求都听策划,绝对不是一个好的程序员,程序员做不到聪明地偷懒,浪费大把时间在产出比低的事情上,其个人的价值是无法最大化的。甚至只能在当一辈子打工人,逃不出这仓鼠滚轮游戏
我遇到一个问题,如果下面是摇杆,然后拖动操作滑出摇杆范围,OnPointerUp和OnEndDrag就没法穿透下去,或者说找不到正确的接收者
大佬,我像问下不同Canvas下的组件可以互相渗透嘛?
可以的, 但是代码里要指定一下,
如果一个穿透按钮下面子物体图片了响应了穿透事件,那会不会无限循环触发导致堆栈溢出
事件只会向下渗透
我之前的项目里也有这样的需求,不过我是通过增加一个全局的点击监听来实现的,监听到PointerDown事件的时候检查是否在自身UI的Rect中,这样可以不用魔改EventSystem
哈哈,我的滑动列表里有button,在滑动结束的时候会触发button的点击
这个问题我们也遇到了,需要判断一下
我也遇到这个问题了,请问雨松MOMO,具体怎么判断?
哈哈 遇到这个需求太正常了,以前都是直接在Update之类的检测点击,然后判断一下点击的东西是否自己,不是就关掉