UGUI內核大探究(一)EventSystem

UGUI是Unity3D官方推出的UI系統,爲了更好的使用UGUI,咱們就須要去了解它。

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自己並無太多東西,可是畢竟輸入模塊裏面仍是保存了一些數據的。

相關文章
相關標籤/搜索