一、继承MonoBehaviour单例模式基类的特点
- MonoBehaviour 不允许
new 创建实例,不存在公共构造函数破坏问题
- 通常不涉及多线程,可忽略线程访问上锁
二、手动挂载式继承MonoBehaviour单例模式基类
1. 特点
- 需要手动将脚本挂载到场景物体上
- 依赖 Awake 初始化
instance
- 容易破坏单例唯一性
2. 什么时候非常推荐使用它?
- 该对象在场景中已经设置好(UI、音效、参数较多等)
- 需要把场景上物体拖入(Canvas、AudioSource、相机)控制这些物体的跨场景持久化
- Prefab 已经有复杂结构,不可能用 new GameObject 替代
3. 使用示例
不跨场景持久化
//写法一(推荐 简单方便)
using UnityEngine;
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance => instance;
protected virtual void Awake()
{
instance = this as T; // 必须在 Awake 中初始化
}
}
//写法二
using UnityEngine;
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance
{
get
{
return instance;
}
}
protected virtual void Awake()
{
instance = this as T; // 必须在 Awake 中初始化
}
}
跨场景持久化
using UnityEngine;
public class SingletonMono<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance => instance;
protected virtual void Awake()
{
if(instance != null)
{
Destroy(this.gameObject);
return;
}
instance = this as T; // 必须在 Awake 中初始化
DontDestroyOnLoad(this.gameObject);
}
}
三、自动挂载式继承MonoBehaviour单例模式基类(推荐)
1. 特点
- 无需手动挂载脚本
- 在第一次访问
Instance 时自动创建物体并挂载脚本
- 保证单例唯一性
- 支持跨场景持久化(
DontDestroyOnLoad)
2. 什么时候非常推荐使用它?
- 管理器不需要 Inspector 配置
- 希望自动创建,使用即存在
- GameManager、TimerManager、PoolManager(纯逻辑)
3. 使用示例
using UnityEngine;
public class SingletonAutoMono<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
//选择在Instance属性里实现创建物体、添加脚本、场景不销毁逻辑,而不是Awkae里实现,是因为其它脚本调用该单例时直接访问Instance,如果Instance里没有创建物体逻辑,那么该单例的Awake也不会被Unity运行
public static T Instance
{
get
{
if (instance == null)
{
// 动态创建物体
GameObject obj = new GameObject(typeof(T).Name);
// 为物体添加脚本
instance = obj.AddComponent<T>();
// 场景切换不销毁
DontDestroyOnLoad(obj);
}
return instance;
}
}
}