事件系統EventSystem不僅可以用於UI,對於場景中的對象也同樣適用,以下主要介紹在場景中的使用
1、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
系統)通知目標對象,那么這兩個組件支持的事件主要有以下:
-
IPointerEnterHandler - OnPointerEnter - Called when a pointer enters the object
-
IPointerExitHandler - OnPointerExit - Called when a pointer exits the object
-
IPointerDownHandler - OnPointerDown - Called when a pointer is pressed on the object
-
IPointerUpHandler - OnPointerUp - Called when a pointer is released (called on the original the pressed object)
-
IPointerClickHandler - OnPointerClick - Called when a pointer is pressed and released on the same object
-
IInitializePotentialDragHandler - OnInitializePotentialDrag - Called when a drag target is found, can be used to initialise values
-
IBeginDragHandler - OnBeginDrag - Called on the drag object when dragging is about to begin
-
IDragHandler - OnDrag - Called on the drag object when a drag is happening
-
IEndDragHandler - OnEndDrag - Called on the drag object when a drag finishes
-
IDropHandler - OnDrop - Called on the object where a drag finishes
-
IScrollHandler - OnScroll - Called when a mouse wheel scrolls
-
IUpdateSelectedHandler - OnUpdateSelected - Called on the selected object each tick
-
ISelectHandler - OnSelect - Called when the object becomes the selected object
-
IDeselectHandler - OnDeselect - Called on the selected object becomes deselected
-
IMoveHandler - OnMove - Called when a move event occurs (left, right, up, down, ect)
-
ISubmitHandler - OnSubmit - Called when the submit button is pressed
-
ICancelHandler - OnCancel - Called when the cancel button is pressed
只要目標對象的mono腳本實現了以上接口,那么輸入模塊會將檢測到的事件通過這些接口通知給目標對象。參考:
http://docs.unity3d.com/Manual/SupportedEvents.html
如果你自定義了自己的輸入模塊,那么以上這些事件肯定是不能用的了。
2、接收輸入事件的方式
1)、自行繼承接口實現監聽在mono腳本中繼承輸入模塊提供的事件接口,如下圖。接口的定義方式也可以查下官方手冊,
http://docs.unity3d.com/ScriptReference/EventSystems.IBeginDragHandler.html
這邊有每一個接口的定義方式,放心大膽地點進去。另外,添加ObjChooseEvent組件的對象,一定要有
Collider哦。
[圖片上傳失敗...(image-374a6a-1511317463227)]
2)、通過EventTrigger組件監聽事件這是一個官方組件。在需要監聽事件的對象上,掛上這個組件,然后在Inspector面板展開配置,你會看到這個組件提供了所有輸入模塊支持的事件類型的監聽,如下圖。
[圖片上傳失敗...(image-60a398-1511317463227)]
這種方式的優點是,當你選中一個你要監聽的類型,你可以為這個事件類型添加多個監聽接口,統一管理,可以清楚的知道到底哪些地方響應了這個事件呢。如果是繼承Interface的方式,它將會分散在N個腳本里,一旦出現問題,那查起來一定會很酸爽。
但是這種通過配置的方式,一旦項目多人協作,項目的復雜度起來,這種拖來拽去的配置終究是會有很多問題的,比如某個組件刪除,比如響應接口改了個名字
~~
都會導致配置丟失,而問題又不能及時發現。又或者程序的監聽接口因為某些條件而不同。所以也許你會需要第三種方式。
3)、動態添加
EventTrigger
組件或者修改組件[圖片上傳失敗...(image-537700-1511317463227)]
其實http://www.cnblogs.com/zou90512/p/3995932.html
這位同學的博客對這三種方法都做了很詳細的說明。只不過EventTrigger對外提供的接口不是很友好,導致我們需要添加一個監聽,仿佛繞了N了山路彎彎,看着就心情不愉快……反而是這位博主后面說的Button的
Click
事件的實現方式有點意思……如果項目有需要,也許我們也可以這么做……
五、
EventSystem
組件提供的一些有意思的接口
其實文檔都有
http://docs.unity3d.com/ScriptReference/EventSystems.EventSystem.html
只是也許你沒有注意。
點擊
EventSystem
對象,你可以看到運行時候的一些詳細數據:
[圖片上傳失敗...(image-d62929-1511317463227)]
變量:
firstSelectedGameObject
:這個值可以在面板設置,如果你需要游戲在啟動的時候自動選中某個對象,需要鼠標的那一下點擊。
currentSelectedGameObject
:當前選中的對象,你可以通過這個值判斷當前是否鼠標點擊在對象上,因為也許你有拖動攝像機的功能,但是你又不喜歡點擊某些對象的時候這個功能又被響應,所以通過這個變量判斷是一個很好的辦法。
接口:
IsPointerOverGameObject
:當前鼠標是否在事件系統可以檢測的對象上。
SetSelectedGameObject
:這個接口也許你會忽略,但是它很棒。因為你點擊場景對象的時候,如果不調用這個接口,你的對象是收不到
OnSelect
事件的,
currentSelectedGameObject
的值也不會被設置的,必須在點擊事件里調用這個接口設置選中對象!
Ex
:
public void OnPointerClick(PointerEventData eventData)
{
print ("OnPointerClick...");
currEvent.SetSelectedGameObject(gameObject);
}
不用在場景里找
EventSystem
對象,
EventSystem
組件有一個
current
靜態變量,它就是你要的對象,直接
EventSystem.current即可使用
。
第一次在蠻牛發文章,word中的圖片竟然不能直接copy進來使用……
unity3d deactivatemodule;unity3d系統教程;unity 實現事件派發