unity5.0開發了新的UI系統UGUI,附帶的事件系統EventSystem不僅可以用於UI,對於場景中的對象也同樣適用。網絡上有很多使用說明,但是僅僅是怎么用而已……這篇文章是我翻了無數遍官方手冊整理出來的,包括自己的理解,還有官方文檔的傳送門,也許你會有興趣。
一、EventSystem對象的說明
當我們在場景中創建任一UI對象后,Hierarchy面板中都可以看到系統自動創建了對象EventSystem,可以看到該對象下有三個組件:EventSystem、StandaloneInputModule、TouchInputModule,后面兩個組件都繼承自BaseInputModule。
EventSystem組件主要負責處理輸入、射線投射以及發送事件。一個場景中只能有一個EventSystem組件,並且需要BaseInputModule類型組件的協助才能工作。EventSystem在一開始的時候會把自己所屬對象下的BaseInputModule類型組件加到一個內部列表,並且在每個Update周期通過接口UpdateModules接口調用這些基本輸入模塊的UpdateModule接口,然后BaseInputModule會在UpdateModule接口中將自己的狀態修改成'Updated',之后BaseInputModule的Process接口才會被調用。
BaseInputModule是一個基類模塊,負責發送輸入事件(點擊、拖拽、選中等)到具體對象。EventSystem下的所有輸入模塊都必須繼承自BaseInputModule組件。StandaloneInputModule和TouchInputModule組件是系統提供的標准輸入模塊和觸摸輸入模塊,我們可以通過繼承BaseInputModule實現自己的輸入模塊。
除了以上兩個組件,還有一個很重要的組件通過EventSystem對象我們看不到,它是BaseRaycaster組件。BaseRaycaster也是一個基類,前面說的輸入模塊要檢測到鼠標事件必須有射線投射組件才能確定目標對象。系統實現的射線投射類組件有PhysicsRaycaster, Physics2DRaycaster, GraphicRaycaster。這個模塊也是可以自己繼承BaseRaycaster實現個性化定制。
總的來說,EventSystem負責管理,BaseInputModule負責輸入,BaseRaycaster負責確定目標對象,目標對象負責接收事件並處理,然后一個完整的事件系統就有了。
另外,其實這些說明官方都有提供,這里也就是把英文譯成了中文,並整理下,加上自己的理解,有問題的地方請各路神仙多多指教。
官方文檔在這里:http://docs.unity3d.com/ScriptReference/EventSystems.EventSystem.html
二、UGUI中的事件系統
根據第一節中的說明,EventSystem和BaseInputModule是粘在一個對象上的,這兩個模塊在EventSystem對象上可以直接看到。那么,BaseRaycaster模塊呢。。。
其實射線檢測,肯定是從攝像機發起的,那么BaseRaycaster模塊也一定和攝像機關系一定不簡單。 對於UI模塊,在Canvas對象下我們可以看到GraphicRaycaster組件。如果Canvas的渲染模式是SceenSpace-Overlay,那么我們是看不到Camera組件的。所以應該是GraphicRaycaster會對UI不同的渲染模式做特殊處理。 因為有GraphicRaycaster組件的原因,Canvas上的所有UI對象,都可以接受輸入模塊發出的事件,具體事件的處理在第四節說明。
三、場景對象中使用事件系統
場景中的非UI對象,如果想要接收輸入模塊的事件,一樣的道理,也需要給攝像機掛上一個射線檢測組件。PhysicsRaycaster, Physics2Draycaster這兩個組件分別是用於3D和2D的場景。當然,還需要場景的對象掛了collider射線才檢測的到。
其實官方對射線檢測也是做了說明的,如果不詳讀手冊是不會發現的,這里是傳送門:
http://docs.unity3d.com/Manual/Raycasters.html
如果場景中只有一個射線檢測源:When a Raycaster is present and enabled in the scene it will be used by the EventSystem whenever a query is issued from an InputModule.
如果場景中有多個射線檢測源:If multiple Raycasters are used then they will all have casting happen against them and the results will be sorted based on distance to the elements.
四、響應事件
1、輸入模塊可以檢測到的事件
StandaloneInputModule和TouchInputModule兩個組件會檢測一些輸入操作,以事件的方式(message系統)通知目標對象,那么這兩個組件支持的事件主要有以下:
只要目標對象的mono腳本實現了以上接口,那么輸入模塊會將檢測到的事件通過這些接口通知給目標對象。參考:http://docs.unity3d.com/Manual/SupportedEvents.html如果你自定義了自己的輸入模塊,那么以上這些事件肯定是不能用的了。
2、接收輸入事件的方式
1)、自行繼承接口實現監聽
在mono腳本中繼承輸入模塊提供的事件接口,如下圖。接口的定義方式也可以查下官方手冊,http://docs.unity3d.com/ScriptReference/EventSystems.IBeginDragHandler.html 這邊有每一個接口的定義方式,放心大膽地點進去。另外,添加ObjChooseEvent組件的對象,一定要有Collider哦。
2)、 通過EventTrigger組件監聽事件
這是一個官方組件。在需要監聽事件的對象上,掛上這個組件,然后在Inspector面板展開配置,你會看到這個組件提供了所有輸入模塊支持的事件類型的監聽,如下圖。

這種方式的優點是,當你選中一個你要監聽的類型,你可以為這個事件類型添加多個監聽接口,統一管理,可以清楚的知道到底哪些地方響應了這個事件呢。如果是繼承Interface的方式,它將會分散在N個腳本里,一旦出現問題,那查起來一定會很酸爽。
但是這種通過配置的方式,一旦項目多人協作,項目的復雜度起來,這種拖來拽去的配置終究是會有很多問題的,比如某個組件刪除,比如響應接口改了個名字~~都會導致配置丟失,而問題又不能及時發現。又或者程序的監聽接口因為某些條件而不同。所以也許你會需要第三種方式。
3)、動態添加EventTrigger組件或者修改組件
程序動態設置實現。我們在日常的開發中,可能需要動態的變更綁定的事件,那么我們如何才能使用C#代碼控制綁定觸發事件呢?下面我們就介紹代碼控制。ScriptControll.cs腳本。
其實http://www.cnblogs.com/zou90512/p/3995932.html 這位同學的博客對這三種方法都做了很詳細的說明。 只不過EventTrigger對外提供的接口不是很友好,導致我們需要添加一個監聽,仿佛繞了N了山路彎彎,看着就心情不愉快……反而是這位博主后面說的Button的Click事件的實現方式有點意思……如果項目有需要,也許我們也可以這么做……
五、EventSystem組件提供的一些有意思的接口
其實文檔都有http://docs.Unity3D.com/ScriptReference/EventSystems.EventSystem.html 只是也許你沒有注意。 變量:
接口:
不用在場景里找EventSystem對象,EventSystem組件有一個current靜態變量,它就是你要的對象,直接EventSystem.current即可使用。
轉自:http://www.360doc.com/content/16/0301/11/13726687_538487422.shtml
