MonoSingleton
Coding Style wiki
MonoSingleton<T> 為 SingletonSystem 的 MonoBehaviour 單例基類 (線程鎖保護),取得實例時會優先查找 場景上的既有實例,否則自動建立 GameObject 掛載組件,支持 DontDestroyOnLoad 跨場景常駐控制,並以 OnCreate / OnStart / OnRelease 生命週期掛勾取代 Unity 的 Awake / Start / OnDestroy。
| 命名空間 | OxGKit.SingletonSystem |
| 類型 | public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T> |
| 原始碼 | MonoSingleton.cs |
using OxGKit.SingletonSystem;
提醒 不需要掛載於 GameObject 的純資料或邏輯管理類,請改用 NewSingleton。
快速上手
using OxGKit.SingletonSystem;
public class GameManager : MonoSingleton<GameManager>
{
protected override void OnCreate() { /* Call by Unity.Awake */ }
protected override void OnStart() { /* Call by Unity.Start */ }
protected override void OnRelease() { /* Call by Unity.OnDestroy */ }
public void SaveGame() { /* ... */ }
}
// 取得實例並訪問 (場景查找或自動建立,預設 DontDestroyOnLoad)
GameManager.GetInstance().SaveGame();
// 場景限定單例 (隨場景卸載銷毀)
GameManager.GetInstance(dontDestroyOnLoad: false);
// 開機明確初始實例 (warm-up)
GameManager.InitInstance();
// 銷毀實例 (連同 GameObject)
GameManager.DestroyInstance();
通用規則
生命週期對應
基類已將 Awake()、Start()、OnDestroy() 實作為私有方法,並以旗標防護對應觸發以下掛勾:
| Unity 方法 | 掛勾 | 旗標 |
|---|---|---|
Awake | OnCreate | isCreated |
Start | OnStart | isStarted |
OnDestroy | OnRelease | isReleased (並重置 isCreated、isStarted 與實例引用) |
重要 不可實作 Awake()、Start()、OnDestroy() (基類已佔用),其餘 Unity 方法 (Update、OnEnable 等) 皆可正常實作。
實例建立規則
- 場景預先放置:實例於
Awake自動註冊為單例,並依 Inspector 上的 dontDestroyOnLoad 欄位決定是否常駐 (詳見模塊介紹)。 - 程式動態建立:呼叫 GetInstance 時若無實例,會查找場景既有實例 (
FindObjectsOfType取第一個),否則以new GameObject(typeof(T).Name)自動建立並掛載組件。
注意 GetInstance 僅於 Play Mode 進行實例建立 (Application.isPlaying)。
注意 同一類型於場景上放置多個實例時不會自動去重 (查找取第一個),請避免於多場景 (Additive) 重複放置。
提醒 於 OnCreate / OnStart 註冊的事件,請於 OnRelease 解除註冊,避免常駐單例累積失效委派;於關閉/銷毀流程中訪問單例,建議先以 CheckInstanceExists 檢查,避免於退出階段又重新建立實例。
成員
| 成員 | 說明 |
|---|---|
public bool dontDestroyOnLoad | (實例欄位) 是否於 Awake 進行 DontDestroyOnLoad 常駐標記,預設 true,場景預先放置時可於 Inspector 配置。 |
public static bool isCreated | OnCreate 是否已觸發。 |
public static bool isStarted | OnStart 是否已觸發。 |
public static bool isReleased | 實例是否已銷毀 (OnRelease 已觸發),新實例 Awake 時會重置為 false。 |
實例管理
方法總覽
| 方法 | 說明 |
|---|---|
| GetInstance | 取得單例實例 (場景查找或自動建立)。 |
| InitInstance | 初始單例實例 (等同呼叫 GetInstance)。 |
| CheckInstanceExists | 檢查實例是否存在。 |
| DestroyInstance | 銷毀單例實例。 |
GetInstance
public static T GetInstance(bool dontDestroyOnLoad = true)
取得單例實例 (線程鎖保護)。若實例尚不存在 (僅於 Play Mode),會優先查找場景上的既有實例,否則自動建立 new GameObject(typeof(T).Name) 並掛載組件;dontDestroyOnLoad 參數為 true 時會標記實例並執行 DontDestroyOnLoad。
// 需要跨場景常駐 (預設)
GameManager.GetInstance();
// 不需要跨場景常駐 (首次取得時設定一次即可)
StageManager.GetInstance(dontDestroyOnLoad: false);
注意 dontDestroyOnLoad 參數於首次建立實例時生效,請於第一次取得實例的呼叫點決定並保持一致。
InitInstance
public static void InitInstance(bool dontDestroyOnLoad = true)
初始單例實例 (等同呼叫 GetInstance),適合於開機流程明確控制建立順序 (warm-up),避免延遲建立造成的順序問題。
private void Awake()
{
GameManager.InitInstance();
AudioManager.InitInstance();
}
CheckInstanceExists
public static bool CheckInstanceExists()
檢查實例是否存在 (不會觸發建立)。
if (GameManager.CheckInstanceExists())
GameManager.GetInstance().SaveGame();
DestroyInstance
public static void DestroyInstance(bool gameObjectIncluded = true)
銷毀單例實例;gameObjectIncluded 為 true 時連同 GameObject 一併銷毀,為 false 時僅銷 毀組件本身。銷毀後會觸發 OnRelease 並重置狀態旗標與實例引用,之後可再重新建立新實例。
// 連同 GameObject 一併銷毀 (預設)
GameManager.DestroyInstance();
// 僅銷毀組件本身 (保留 GameObject)
GameManager.DestroyInstance(gameObjectIncluded: false);
生命週期掛勾
方法總覽
| 方法 | 說明 |
|---|---|
| OnCreate | 由 Unity Awake 觸發。 |
| OnStart | 由 Unity Start 觸發。 |
| OnRelease | 由 Unity OnDestroy 觸發。 |
OnCreate
protected abstract void OnCreate()
由 Unity Awake 觸發 (以 isCreated 旗標防護僅觸發一次),於此實作初始邏輯。
OnStart
protected abstract void OnStart()
由 Unity Start 觸發 (以 isStarted 旗標防護僅觸發一次),於此實作啟動邏輯。
OnRelease
protected abstract void OnRelease()
由 Unity OnDestroy 觸發,於此實作釋放邏輯 (解除事件註冊、釋放資源);觸發後 isReleased 為 true,並重置 isCreated、isStarted 與實例引用。