ScriptableObject as Event
ScriptableObject
可以用來作為事件系統的一部分。這種方法可以幫助我們在不同的 MonoBehaviour
之間進行通信,而不需要它們彼此知道對方的存在,從而實現鬆耦合。
- 為觀察者模式(Observer Pattern)的一種實作
首先要建立 GameEvent
與 GameEventListener
。它們兩個互相依賴
GameEvent
- 含有一個
GameEventListener
列表用來保存要聽取該事件的聽眾, - 使用
RegisterListener
來註冊聽眾 - 使用
UnregisterListener
將聽眾移出 - 使用
Raise
觸發聽眾註冊的事件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24[ ]
public class GameEvent : ScriptableObject
{
private readonly List<GameEventListener> eventListeners =
new List<GameEventListener>();
public void Raise()
{
for (int i = eventListeners.Count - 1; i >= 0; i--)
eventListeners[i].OnEventRaised();
}
public void RegisterListener(GameEventListener listener)
{
if (!eventListeners.Contains(listener))
eventListeners.Add(listener);
}
public void UnregisterListener(GameEventListener listener)
{
if (eventListeners.Contains(listener))
eventListeners.Remove(listener);
}
}
GameEventListener
- 含有一個要監聽的事件參考
Event
- 含有一個當監聽到後,要做出的回應
Response
OnEnable
中將自己註冊到Event
中OnDisable
中將自己從Event
中移出OnEventRaised
中呼叫回應的方法
1 | public class GameEventListener : MonoBehaviour |
接著在 Unity 編輯器中建立一個 ScriptableObject
實體,並命名為 ClickEvent
建立一個 DoSomethingWhenClick
的遊戲物件(GameObject
) ,並添加以下腳本,這個遊戲物件有一個公開方法 JustDoIt
,當事件發生時,要被呼叫。
1 | public class DoSomethingWhenClick : MonoBehaviour |
建立一個 EventListener
的 GameObject
,將 GameEventListener
腳本添加到這個 EventListener
GameObject
中。
- 接下來將前面建立的
ScriptableObject
實體ClickEvent
,拖放到,EventListener
中的 Event 欄位,表示這個EventListener
要監聽的事件是ClickEvent
- 然後設定聽到之後要做的事。將
DoSomethingWhenClick
遊戲物件放到 Response 欄位,並設定要執行該物件的公開方法JustDoIt
接著建立事件發起的物件,這邊建立兩個, RaiseClickableCircle
與 RaiseClickableButWithUnityEvent
RaiseClickableCircle
的腳本如下,它主要是直接使用 GameEvent
作為參考,其缺點是只能用一個 Event
1 | public class RaiseClickableCircle : MonoBehaviour |
RaiseClickableButWithUnityEvent
幾乎與 RaiseClickableCircle
一模一樣,差別在於是使用 UnityEvent
,這樣可以放置多個 Event,當觸發 Raise
時在裡面的 Event 都會觸發。
1 | public class RaiseClickableButWithUnityEvent : MonoBehaviour |
最後執行,並點擊畫面上的圓形或是方形,可以發現都會觸發 DoSomethingWhenClick
的 JustDoIt
方法,而 RaiseClickableButWithUnityEvent
, RaiseClickableCircle
與 DoSomethingWhenClick
完全不知曉對方的存在。
使用基於事件架構(event-based architecture
)的好處是,它不會每一幀都在執行,只有在當事件發生時才會執行,因此效率會比在 MonoBehaviour
的 Update
方法中執行好。
Reference: