UGUI代碼開源,咱們能夠從bitbucket下載到源碼。ide
雖然Unity官方喜歡藏着掖着,例如RectTransform和Canvas系列的源碼都放在了UnityEngine裏面,可是這並不妨礙咱們對已開源的代碼進行分析(其實多少也有些妨礙吧。。。)ui
今天咱們就探究了一下UGUI的事件系統EventSystem。this
雖然名字起得很大,可是實際上EventSystem處理和管理的實際上是點擊、鍵盤輸入、觸摸等事件,因此應該成爲輸入事件系統InputEventSystem更爲恰當。spa
咱們看到EventSystem最開始聲明瞭一個List和一個變量.net
[csharp] view plain copy private List<BaseInputModule> m_SystemInputModules = new List<BaseInputModule>(); private BaseInputModule m_CurrentInputModule;
系統輸入模塊表和當前輸入模塊。code
BaseInputModule是一個抽象類,PointerInputModule繼承自它,一樣也是抽象類,而StandaloneInputModule和TouchInputModule又繼承自PointerInputModule。StandaloneInputModule是面向「PC, Mac& Linux Standalone」這個平臺的輸入模塊,而TouchInputModule是面向「iOS」、「Android」等可觸摸移動平臺的輸入模塊。orm
EventSystem會每一幀都處理這些輸入模塊,首先是調用TickModules方法,更新每個InputModule。對象
而後遍歷m_SystemInputModules判斷這些module是否支持當前的平臺(例如StandaloneInputModule須要判斷是否鼠標已鏈接,而TouchInputModule須要判斷是否支持觸摸)且module是否可激活(可激活條件祥參StandaloneInputModule和TouchInputModule的源碼)。blog
若是有符合條件的module便賦值給m_CurrentInputModule(當前輸入模塊)並break。排序
若是沒有符合條件的module便選取第一個支持當前平臺的module做爲m_CurrentInputModule。
最後若是m_CurrentInputModule的值變化了而且m_CurrentInputModule不爲null便調用:
而這個方法會將各類輸入事件(如點擊、拖拽等事件)傳遞給EventSystem當前選中的GameObject(m_CurrentSelected)。
[csharp] view plain copy m_CurrentInputModule.Process();
而m_CurrentSelected大部分狀況是Selectable組件(繼承自它的有Button、Dropdown、InputField等組件)設置的,相關代碼咱們會在後續的文章中介紹。
而設置m_CurrentSelected的時候,會經過ExecuteEvents這個類對以前的對象執行一個被取消事件,且對新選中的對象執行一個被選中事件。這就是OnSelect和OnDeselect兩個方法的由來。
EventSystem的RaycastAll方法使用射線從相機到某個點(設爲點E)照射在UI上,而後對被照射到的全部對象進行排序,大體是遠近排序。
而這個方法實在PointerInputModule中使用的,若是點擊(或觸摸)事件移動的時候,被該事件影響的對象也會發生變化,經過RaycastAll方法(傳入的eventData中的position屬性做爲點E)得到到第一個被射線照射到的對象,若是與以前的對象不一樣,便變動對象(同時會回調原對象的OnPointerExit和新對象的OnPointerEnter方法)。
IsPointerOverGameObject是EventSystem類裏特別經常使用的一個方法,用於判斷是否點擊在UI上,具體是在PointerInputModule中實現的,之後咱們研究UGUI的輸入模塊的時候會深刻講解,歸納一下就是判斷當前是否存在某個鍵位(默認是-1鼠標左鍵)的數據。
最後咱們注意到EventSystem有一個static屬性:
[csharp] view plain copy public static EventSystem current { get; set; }
由於是靜態屬性,因此只存在一個current,而並不會每一個實例對象會有一個.
當一個EventSystem組件OnEnable的時候會將這個對象賦值給current。參考OnEnabled與OnDisabled。
[csharp] view plain copy protected override void OnEnable() { base.OnEnable(); if (EventSystem.current == null) EventSystem.current = this; #if UNITY_EDITOR else { Debug.LogWarning("Multiple EventSystems in scene... this is not supported"); } #endif }
OnDisable的時候會將current賦值爲null(當current==this)。參考OnEnabled與OnDisabled。
[csharp] view plain copy protected override void OnDisable() { if (m_CurrentInputModule != null) { m_CurrentInputModule.DeactivateModule(); m_CurrentInputModule = null; } if (EventSystem.current == this) EventSystem.current = null; base.OnDisable(); }
這就是爲何咱們在Unity Editor裏面增長多個EventSystem的時候會報警告。
固然在遊戲運行的時候,咱們也不能隨意的增長刪除EventSystem,一來彷佛並無什麼必要,二來雖然EventSystem自己並無太多東西,可是畢竟輸入模塊裏面仍是保存了一些數據的。