跳到主要内容

MonoSingleton

重要 注意 提醒

Coding Style wiki


MonoSingleton<T>SingletonSystemMonoBehaviour 单例基类 (线程锁保护),获取实例时会优先查找场景上的既有实例,否则自动创建 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 方法挂钩标记
AwakeOnCreateisCreated
StartOnStartisStarted
OnDestroyOnReleaseisReleased (并重置 isCreatedisStarted 与实例引用)

重要 不可实现 Awake()Start()OnDestroy() (基类已占用),其余 Unity 方法 (UpdateOnEnable 等) 均可正常实现。

实例创建规则

  1. 场景预先放置:实例于 Awake 自动注册为单例,并依 Inspector 上的 dontDestroyOnLoad 字段决定是否常驻 (详见模块介绍)。
  2. 代码动态创建:调用 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 isCreatedOnCreate 是否已触发。
public static bool isStartedOnStart 是否已触发。
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)

销毁单例实例;gameObjectIncludedtrue连同 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 触发,于此实现释放逻辑 (解除事件注册、释放资源);触发后 isReleasedtrue,并重置 isCreatedisStarted 与实例引用。