• UGUI的事件系统分析


    UGUI的源码还是非常清晰的,打开源码可以发现, 从UGUI的源码可知:在EventSystem中调用每一帧函数来实现:

       private void TickModules()
        {
            for (var i = 0; i < m_SystemInputModules.Count; i++)
            {
                if (m_SystemInputModules[i] != null)
                    m_SystemInputModules[i].UpdateModule();
            }
        }
    

    这段代码可以得到当前输入InputModule的position,接着在GetMousePointerEventData函数中存在这一段代码:

     public void RaycastAll(PointerEventData eventData, List<RaycastResult> raycastResults)
        {
            raycastResults.Clear();
            var modules = RaycasterManager.GetRaycasters();
            for (int i = 0; i < modules.Count; ++i)
            {
                var module = modules[i];
                if (module == null || !module.IsActive())
                    continue;
    
            module.Raycast(eventData, raycastResults);
        }
    
        raycastResults.Sort(s_RaycastComparer);
    }
    

    你会发现s_RaycastComparer这样一个函数,该函数就是对所有射线射到的物体进行排序,哈哈,终于找到这个函数了,看看它的实现:

     private static int RaycastComparer(RaycastResult lhs, RaycastResult rhs)
        {
            if (lhs.module != rhs.module)
            {
                if (lhs.module.eventCamera != null && rhs.module.eventCamera != null && lhs.module.eventCamera.depth != rhs.module.eventCamera.depth)
                {
                    // need to reverse the standard compareTo
                    if (lhs.module.eventCamera.depth < rhs.module.eventCamera.depth)
                        return 1;
                    if (lhs.module.eventCamera.depth == rhs.module.eventCamera.depth)
                        return 0;
    
                return -1;
            }
    
            if (lhs.module.sortOrderPriority != rhs.module.sortOrderPriority)
                return rhs.module.sortOrderPriority.CompareTo(lhs.module.sortOrderPriority);
    
            if (lhs.module.renderOrderPriority != rhs.module.renderOrderPriority)
                return rhs.module.renderOrderPriority.CompareTo(lhs.module.renderOrderPriority);
        }
    
        if (lhs.sortingLayer != rhs.sortingLayer)
        {
            // Uses the layer value to properly compare the relative order of the layers.
            var rid = SortingLayer.GetLayerValueFromID(rhs.sortingLayer);
            var lid = SortingLayer.GetLayerValueFromID(lhs.sortingLayer);
            return rid.CompareTo(lid);
        }
    
    
        if (lhs.sortingOrder != rhs.sortingOrder)
            return rhs.sortingOrder.CompareTo(lhs.sortingOrder);
    
        if (lhs.depth != rhs.depth)
            return rhs.depth.CompareTo(lhs.depth);
    
        if (lhs.distance != rhs.distance)
            return lhs.distance.CompareTo(rhs.distance);
    
        return lhs.index.CompareTo(rhs.index);
    }
    

    来分析下这段代码的实现:

    • 如果Canvas指定了摄像机,就按照摄像机的depth排序。

    • 按照sortOrderPriority的顺序排序。

    • 按照renderOrderPriority排

    • 按depth排(针对GraphicRaycaster),其他两种物理射线(PhysicsRaycaster,Physics2DRaycaster)的depth为0。

    • 按distance排、这里是针对两种物理射线的方式,为射线到物体的距离。

    • 按index排,无论是哪种射线模式,都会将射线碰撞到的UI物体压入到列表中,这里的index就是列表的索引值。

    如何找到已经实现了该事件的组件?

    在ExecuteEvents的类中有这样一段代码:

     private static void GetEventChain(GameObject root, IList<Transform> eventChain)
        {
            eventChain.Clear();
            if (root == null)
                return;
    
        var t = root.transform;
        while (t != null)
        {
            eventChain.Add(t);
            t = t.parent;
        }
    }
    

    这段代码一直在点击的gameobject上递归寻找它的父类,然后加入到列表当中。只要有一个父类实现了该接口就会触发该接口事件。然后返回该gameObject。

    做实验的话,可以在父对象上实现一个接口函数,点击子对象发现父对象的函数触发了。自己亲测可行。

  • 相关阅读:
    .Net自动生成Html新闻系统V1.0 Beta 下载
    Visual Studio .NET 2003中自己找到的一个小技巧[图]
    多表连接的SQL写法(SqlServer、Oracle)
    在线人数统计 V1.0(Asp.net+ SqlServer) 源码下载
    Visual Studio 2005安装后,原来的Asp.net1.1不能执行的解决方法。
    [函数]截取固定长的字符串(双字节的计2位)
    [原创]asp.net 2.0下的自定义树(myTreeView)
    通用的数据库操作助手类
    关于时间国际化的方案
    HTTPS Cipher Suite问题
  • 原文地址:https://www.cnblogs.com/master-image/p/5240428.html
Copyright © 2020-2023  润新知