单例模式
🎯 单例实现
一、不继承 MonoBehaviour
1. 单例内部 没有跨场景物体
✔ 饿汉式(立即创建,推荐)
public class Manager
{
private static Manager instance = new Manager();
public static Manager Instance => instance;
private Manager() {}
}
适用场景
- 纯逻辑类:ConfigManager、SaveManager、EventBus
- 不需要场景对象
- 启动后总会用到(无资源浪费)
✔ 懒汉式(延迟创建)
public class Manager
{
private static Manager instance;
public static Manager Instance
{
get
{
if (instance == null)
instance = new Manager();
return instance;
}
}
private Manager() {}
}
适用场景
- 创建成本大
- 不一定会被访问
- 不在多线程环境中
2. 单例内部 有跨场景的物体(例如 Canvas)(推荐继承MonoBehaviour,将要跨场景的物体拖入Inspect)
❌ 方式一 — 依赖场景已有物体(不推荐)
public class Manager
{
private static Manager instance = new Manager();
public static Manager Instance => instance;
private Manager()
{
canvas = GameObject.Find("Canvas").transform;
DontDestroyOnLoad(canvas);
}
}
为什么不推荐?
- 多场景出现多个 Canvas 会出错
- 完全依赖场景资源,不稳定
✔ 方式二 — 动态加载 Prefab(推荐)
public class Manager
{
private static Manager instance = new Manager();
public static Manager Instance => instance;
private Manager()
{
canvas = Object.Instantiate(Resources.Load<GameObject>("UI/Canvas")).transform;
DontDestroyOnLoad(canvas);
}
}
推荐用于:
- UIManager(如果你不用 MonoBehaviour)
- 规避场景中重复对象
- Prefab 已经配置完成(带 UI 参数、组件等)
二、继承 MonoBehaviour
Unity 不允许 new 出 MonoBehaviour,因此必须通过以下两种方式:
- 场景挂载 + Awake 初始化(场景中已有该物体)
- 自动创建(懒加载) + AddComponent
下面分两类说明:
1. 管理器物体 不跨场景
✔ 场景手动挂载 + Awake 设置
public class Manager : MonoBehaviour
{
private static Manager instance;
public static Manager Instance => instance;
private void Awake();
{
instance = this
}
}
适用场景
- 跟运行场景强绑定
- 不需要持久化
- 例如:局部战斗管理器、场景相机控制器
✔ 自动挂载(懒加载)
public class Manager : MonoBehaviour
{
private static Manager instance;
public static Manager Instance
{
get
{
if (instance == null)
{
GameObject obj = new GameObject("Manager");
obj.name = typeof(T).Name;
instance = obj.AddComponent<Manager>();
}
return instance;
}
}
}
适用场景
- 不需要 Inspector 配置
- 完全逻辑类但需要 MonoBehaviour 功能(协程、Update)
2. 管理器物体 需要跨场景(DontDestroyOnLoad)
🟦 方式一(强烈推荐用于需要 prefab/配置的对象)
✔ 场景挂载 + Awake 检查重复(最安全、最通用)
public class Manager : MonoBehaviour
{
private static Manager instance;
public static Manager Instance => instance;
private void Awake()
{
if (instance != null)
{
Destroy(gameObject);
return;
}
instance = this;
DontDestroyOnLoad(gameObject);
}
}
👍 什么时候非常推荐使用它?
- 该对象在场景中已经设置好(UI、音效、参数较多等)
- 你需要 Inspector 配置(特别是 Canvas、AudioSource、相机)
- Prefab 已经有复杂结构,不可能用 new GameObject 替代
- 多人协作时避免出现多个管理器竞争
🟩 方式二(推荐用于纯逻辑管理器)
✔ 自动创建 + DontDestroyOnLoad(懒加载)
public class Manager : MonoBehaviour
{
private static Manager instance;
public static Manager Instance
{
get
{
if (instance == null)
{
GameObject obj = new GameObject("Manager");
obj.name = typeof(T).Name;
instance = obj.AddComponent<Manager>();
DontDestroyOnLoad(obj);
}
return instance;
}
}
}
👍 什么时候非常推荐使用它?
- 管理器不需要 Inspector 配置
- 希望自动创建,使用即存在
- GameManager、TimerManager、PoolManager(纯逻辑)

浙公网安备 33010602011771号