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: