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主要在輸入模塊裏被調用,用於獲取某個輸入事件的響應對象。(詳細分析會在後續的文章中介紹)