以前写过一篇类似的文章用于解决新手引导的问题, Unity3D研究院之将UI的点击事件渗透下去(九十) 最近策划又提出一个需求,Tips窗口打开以后点击空白区域关掉,但是如果空白区域下有按钮滑动输入一类的要关掉Tips的同时要响应相面的事件,所以透下的事件就要比较完整了。开始我觉得这个需求很不合理,但是他们给我找了个这样实现的游戏,我瞬间只能服了。
代码在项目中已经测试了一段时间了,同时也欢迎大家测试。
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程序研究院 发表
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!




我一般做法tips后面一个透明ui很大,可以点击关闭,但是识别滚动关闭就不行了,这个需求太变态了。
这种需求,一定要回怼,就算有游戏实现了就一定就是好的吗?时间要花在刀刃上,如果什么需求都听策划,绝对不是一个好的程序员,程序员做不到聪明地偷懒,浪费大把时间在产出比低的事情上,其个人的价值是无法最大化的。甚至只能在当一辈子打工人,逃不出这仓鼠滚轮游戏
我遇到一个问题,如果下面是摇杆,然后拖动操作滑出摇杆范围,OnPointerUp和OnEndDrag就没法穿透下去,或者说找不到正确的接收者
大佬,我像问下不同Canvas下的组件可以互相渗透嘛?
可以的, 但是代码里要指定一下,
如果一个穿透按钮下面子物体图片了响应了穿透事件,那会不会无限循环触发导致堆栈溢出
事件只会向下渗透
我之前的项目里也有这样的需求,不过我是通过增加一个全局的点击监听来实现的,监听到PointerDown事件的时候检查是否在自身UI的Rect中,这样可以不用魔改EventSystem
哈哈,我的滑动列表里有button,在滑动结束的时候会触发button的点击
这个问题我们也遇到了,需要判断一下
我也遇到这个问题了,请问雨松MOMO,具体怎么判断?
哈哈 遇到这个需求太正常了,以前都是直接在Update之类的检测点击,然后判断一下点击的东西是否自己,不是就关掉