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函数中存在这一段代码:code
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这样一个函数,该函数就是对全部射线射到的物体进行排序,哈哈,终于找到这个函数了,看看它的实现:orm
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。
作实验的话,能够在父对象上实现一个接口函数,点击子对象发现父对象的函数触发了。本身亲测可行。