[C#/Unity] 更多 Singleton – More Singleton in Unity
在舊文章 [Unity] 應用 Singleton pattern 及 Unity Component 做系統拆分與管理 – Dividing your game system in unity 中,我開發了一套架構來作為單一 Singleton 的替代方案,用於統一管理會在整個 Unity 專案中使用到的遊戲功能系統。
該篇文章中的 GameSystemMono (即仿 Singlton 的組件) 繼承了 MonoBehaviour,來實現一些設計上的想法。不過帶來優點的同時也產生了一些限制,經過與他人的討論後,認為還是需要一個不依賴 MonoBehaviour 的 Singleton 組件方案,兩者互相補足,而這個想法終於在最近進行了實作。
做為 GameModule 基底的介面 (interface)
上一個 Singleton 系統將組件命名 GameSystemMono;而這次的組件我則命名為 GameModule,下文也會如此稱呼與區分。
而 GameModule 的採用介面 (interface) 來實現,其中 IModular 是必備的,IModuleUpdatable 是有 Update 需求時可以增加的介面。目前只開發了兩個介面,未來如有需要,還能繼續擴充。
1 | using System.Collections; |
採用**介面(interface)而非抽象類別(abstract class)**的原因:
- 因為並沒有繼承 MonoBehaviour,因此並沒有寫為類別的需要。
- C# 不支援多重繼承 (Multiple Inheritance),所以如果採用類別,則會降低組件繼承上的靈活性。
- 介面可以支援多重組合,而且是可以在繼承之外另外加上的,相當於可以將多種類別都轉換成 GameModule 來使用而不受限。
GameModule 的管理器
1 | using System.Collections; |
管理器的實作方式與 GameSystemMono 的管理器大同小異。
在 AddModule() 的時候,必須利用 is 運算子檢查是否有額外的介面被新的 GameModule 所使用。比如發現了 IModuleUpdatable 介面,則要做而外的處理。
對應不同介面,可能也會有特別的 public 方法用於觸發或操作,對於 IModuleUpdatable 介面,我準備了一個 UpdateModule () 來進行觸發。
GameSystemMono 與 GameModule 的比較
GameSystemMono的實作採用繼承 MonoBehaviour,優勢是可以在 Inspector 視窗針對每個組件系統進行參數的設定,並且可以直接使用 Update 等 Unity Message Event 進行動作;缺點則是一定要有個 GameObject 進行載體,而且採用類別繼承的設計,會導致一些彈性上的限制,不需要 MonoBehaviour 功能的組件也會被迫繼承相關特性。
GameModule的實作採用介面 (interface),優勢是可以跟繼承關係並存,切依照需求選擇需要的而外功能介面進行擴充,彈性較高;缺點則是所有的初始化工作就都必須撰寫腳本來完成,而且沒有可以在 Inspector 調整追蹤參數的手段。
就上述的筆記可以看出來,GameSystemMono與GameModule其實是相互補的兩個 Singleton 註冊架構,可以在一個專案中同時採用,依照組件的需求吉特,來決定要包裝成GameSystemMono或是GameModule來管理。
另外還有單一獨立的 Singleton 實作 (如參考所附),如果組件沒有與其他組件互動的需求,只是單單最為一個被呼叫的子系統,也可以採用做為一個簡單易用的方法
單例模式 (Singleton pattern) 是一個相對有較多爭議的設計模式,為了避免在使用的時候會將 Singleton 的缺點凸顯出來,更多的設計考量與深入了解是難免要面對的。
參考
- Singleton in Unity – http://wiki.unity3d.com/index.php/Singleton
- Generic Singleton – http://stackoverflow.com/questions/2319075/generic-singletont