UGUI内核大探究(一)EventSystem咱们探究了事件系统,其中咱们讲到EventSystem能够经过ExecuteEvents这个类来执行事件,那么事件是如何执行的呢?这里涉及到了两个文件EventInterface和ExecuteEvents。ide
按照惯例,附上UGUI源码下载地址。ui
EventInterface声明了一系列interface(能够参考我以前的博客关于接口的介绍),若是常常接触UI的话,我相信你对这些接口必定不陌生。例如IPointerEnterHandler(指针进入事件接口)。一个组件添加这个接口的继承以后,再实现OnPointerEnter方法,即可以接收到指针进入事件,也就是当鼠标滑入对象所在的区域以后,便会回调OnPointerEnter方法。这些接口全都继承自IEventSystemHandler,然后者也是声明在EventInterface里的接口。url
以上这些接口都会在ExecuteEvents里被调用。ExecuteEvents类是个静态类,不能被实例化,全部的公共方法都经过ExecuteEvents.XXXX来调用。ExecuteEvents里声明了一个delegate的类型(能够参考我以前的博客关于委托的介绍)EventFunction,这是一个泛型委托,委托的第一个参数handler能够是不一样的类型。而后对EventInterface里除了IEventSystemHandler外每个接口声明了一个EventFunction类型的委托变量和方法。例如:.net
[csharp] view plain copy private static readonly EventFunction<IPointerEnterHandler> s_PointerEnterHandler = Execute; private static void Execute(IPointerEnterHandler handler, BaseEventData eventData) { handler.OnPointerEnter(ValidateEventData<PointerEventData>(eventData)); }
就是声明了一个参数类型为IPointerEnterHandler的委托变量s_PointerEnterHandler,并实现了委托所执行的方法Execute。指针
而后又声明了一系列属性,这些属性是获取上述委托变量的只读属性,用于在外部调用。code
而外部统一调用执行事件的方法是对象
[csharp] view plain copy public static bool Execute<T>(GameObject target, BaseEventData eventData, EventFunction<T> functor) where T : IEventSystemHandler
咱们先看一下它的使用方法,例如在BaseInputModule里,咱们看到:blog
[csharp] view plain copy ExecuteEvents.Execute(t.gameObject, currentPointerData, ExecuteEvents.pointerEnterHandler);
前两个参数很好理解,第三个参数就是调用了ExecuteEvents里的pointerEnterHandler属性(也就是上面的s_PointerEnterHandler),这样泛型T也就变成了IPointerEnterHandler。继承
Execute方法里面,经过GetEventList得到target上的T类型的组件列表,而后遍历这些组件,并执行接口
[csharp] view plain copy functor(arg, eventData);
以pointerEnterHandler为例,咱们能够了解这个方法实际上执行的是:
[csharp] view plain copy arg.OnPointerEnter(ValidateEventData<PointerEventData>(eventData));
也就是调用了IPointerEnterHandler类型的组件的OnPointerEnter方法。
至此,咱们就了解到了UGUI里的事件是如何执行的:指定某个接口类型,由Execute方法调用目标对象的接口方法。
接着,补充一下ExecuteEvents类里面其余方法的介绍。
ExecuteHierarchy方法会经过GetEventChain获取target的因此父对象,并对这些对象(包括target)执行Execute方法。 GetEventHandler会遍历目标对象及其父对象,判断他们是否包含某个指定接口,若是包含则做为返回值返回。而判断方法是CanHandleEvent,经过GetEventList方法获取target上的T类型的组件列表,判断列表数量不为零。GetEventHandler主要在输入模块里被调用,用于获取某个输入事件的响应对象。(详细分析会在后续的文章中介绍)