欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity 3D UGUI游戏界面 事件系统

程序员文章站 2022-07-12 23:33:46
...

UGUI 所有的事件系统都是依赖 EventSystem 组件完成的,全面取代之前的SendMessage 系统了。

Unity 3D UGUI游戏界面 事件系统

这是运行状态下的EventSystem。

//--UI事件

UI事件依赖于 Graphic Raycaster 组件,它必须绑定在Canvas 组件上,表示这个Canvas 下的所有UI元素支持的事件。

若有多个Canvas ,想让某个Canvas 下的UI不接受点击事件,可以把这个Canvas 的Graphic Raycaster 组件干掉。

Unity3D UGUI 利用EventTrigger实现按钮事件注册等相关

//--RaycastTarget优化

UGUI的点击事件也是基于射线的,如果不需要响应事件,千万不要在Image或 Text 等组件上勾选RaycastTarget。

UI事件会在EventSystem 的Update()方法中调用Process时触发。UGUI会遍历屏幕中所有的RaycastTarget是True的UI,接着就会发射线,并且排序找到玩家最先接触的那个UI,再抛出事件给逻辑层去响应,这样无形中就会带来很多开销。

拓展一下Scene视图,将所有勾选RaycastTarget的UI用线框显示出来。

Unity 3D UGUI游戏界面 事件系统

using UnityEngine;
using UnityEngine.UI;

public class DrawLineRaycastTargetMyTools : MonoBehaviour
{
#if UNITY_EDITOR
    static Vector3[] fourCorners = new Vector3[4];
    private void OnDrawGizmos()
    {
        foreach (MaskableGraphic g in FindObjectsOfType<MaskableGraphic>())
        {
            if (g.raycastTarget)
            {
                RectTransform rectTransform = g.transform as RectTransform;
                rectTransform.GetWorldCorners(fourCorners);
                Gizmos.color = Color.blue;
                for (int i = 0; i < 4; i++)
                {
                    Gizmos.DrawLine(fourCorners[i], fourCorners[(i + 1) % 4]);
                }
            }
        }
    }
#endif
}

//-渗透UI事件

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

public class UIEventPassMyTools : MonoBehaviour, IPointerClickHandler
{
    public void OnPointerClick(PointerEventData eventData)
    {
        //--do
        PassEvent(eventData, ExecuteEvents.pointerClickHandler);
    }

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