Unity3D之事件的穿透和传递

一 , Scene设计

      Ⅰ, A和B是兄弟ide

      Ⅱ, C是A的孩子测试

二, 测试一(穿透测试)

 Ⅰ, 代码spa

A , B , C 分别挂载A.cs , B.cs , C.cs , 分别以下设计

A.cs 代码以下code

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 代码以下blog

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.csit

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

          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上

 

五, 需求: 关闭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

相关文章
相关标签/搜索