Unity3D之事件的穿透和传递
  RlWeLU85QNwT 2023年11月12日 28 0

一 , Scene设计

      Ⅰ, A和B是兄弟

      Ⅱ, C是A的孩子

Unity3D之事件的穿透和传递_传递

二, 测试一(穿透测试)

 Ⅰ, 代码

A , B , C 分别挂载A.cs , B.cs , C.cs , 分别如下

A.cs 代码如下

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

public class A : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("A click");
}
}


B.cs 代码如下

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

public class B : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("B click");
}
}


C.cs 代码如下

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

public class C : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("C click");
}
}


Ⅱ, 测试

      A, 卸载 B 和 C的脚本 B.cs 和 C.cs

          1, 点击C的时候A会触发事件

          2, 点击B的时候A不会触发事件(兄弟拦截了)

     B, 将B 和 C 的 脚本B.cs 和 C.cs重新挂载到B,C上

           1, 点击C的时候A不会触发事件(被C拦截了)

           2, 和上面一样点击B,A也不会触发事件

结论:

①,无论兄弟是否挂载了脚本,都会拦截处于下方得其他兄弟的事件

②,孩子级别比较特殊, 如果孩子挂载脚本,就会拦截父方脚本;反之则不会拦截

三, 测试二(传递测试)

       1, 特殊需求: 无论点击B或者C都会触发下面的A

       B.cs 代码如下

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

public class B : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("B click");
PassEvent(eventData, ExecuteEvents.pointerClickHandler);
}

//把事件透下去
public void PassEvent<T>(PointerEventData data, ExecuteEvents.EventFunction<T> function)
where T : IEventSystemHandler
{
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(data, results);
GameObject current = data.pointerCurrentRaycast.gameObject;
for (int i = 0; i < results.Count; i++)
{
if (current != results[i].gameObject)
{
ExecuteEvents.Execute(results[i].gameObject, data, function);
}
}
}
}


C.cs 代码

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

public class C : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("C click");
PassEvent(eventData, ExecuteEvents.pointerClickHandler);
}


public void PassEvent<T>(PointerEventData data, ExecuteEvents.EventFunction<T> function)
where T : IEventSystemHandler
{
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(data, results);
GameObject current = data.pointerCurrentRaycast.gameObject;
for (int i = 0; i < results.Count; i++)
{
if (current != results[i].gameObject)
{
ExecuteEvents.Execute(results[i].gameObject, data, function);
}
}
}
}


四, 需求:B不需要Event, 但是要透过B可以触发A的Event 

     1, 脚本

using UnityEngine;
using UnityEngine.UI;

public class ImageExtends : Image
{
override public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
return false;//不拦截, (自己也不会触发Event)
}
}

    2, 将脚本挂载到B的GameObject上

Unity3D之事件的穿透和传递_Unity3D_02


五, 需求: 关闭A及A的孩子的Event

     1, A.cs 继承 ICanvasRaycastFilter

     2, 重写 IsRaycastLocationValid() 方法

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

public class A : MonoBehaviour, IPointerClickHandler, ICanvasRaycastFilter
{
[SerializeField]
private bool IsFocus = false;
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("A click");
}



public bool IsRaycastLocationValid(Vector2 sp, Camera eventCamera)
{
return IsFocus;
}
}

当 IsFocus 为false 时, A,C不触发Event

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月12日 0

暂无评论

推荐阅读
  thhXZYsU6mxB   2023年11月02日   40   0   0 Unity3D
  RlWeLU85QNwT   2023年11月12日   21   0   0 事件Unity3D
RlWeLU85QNwT