1.MonoSingleton
代码部分
cs
using UnityEngine;
/// <summary>
/// MonoBehaviour单例基类
/// 需要挂载到GameObject上使用
/// </summary>
public class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
private static T _instance;
private static readonly object _lock = new object();
private static bool _applicationIsQuitting = false;
public static T Instance
{
get
{
if (_applicationIsQuitting)
{
Debug.LogWarning($"[MonoSingleton] Instance '{typeof(T)}' already destroyed on application quit. Won't create again.");
return null;
}
lock (_lock)
{
if (_instance == null)
{
_instance = FindObjectOfType<T>();
if (_instance == null)
{
GameObject singletonObject = new GameObject();
_instance = singletonObject.AddComponent<T>();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// 可选:让单例对象在场景切换时不被销毁
//DontDestroyOnLoad(singletonObject);
}
}
return _instance;
}
}
}
protected virtual void Awake()
{
if (_instance == null)
{
_instance = this as T;
DontDestroyOnLoad(gameObject);
}
else if (_instance != this)
{
Debug.LogWarning($"Another instance of {typeof(T)} already exists. Destroying this one.");
Destroy(gameObject);
}
}
protected virtual void OnApplicationQuit()
{
_applicationIsQuitting = true;
}
protected virtual void OnDestroy()
{
if (_instance == this)
{
_instance = null;
}
}
}
说明
继承MonoSingleton的物体需要能挂载到场景物体上,即继承MonoBehaviour
我在MonoSingleton中将DontDestroyOnLoad(singletonObject)取消掉了,如果需要跨场景的话需要在继承的脚本中重写Awake方法
cs
protected override void Awake()
{
base.Awake();
DontDestroyOnLoad(gameObject);
}
2.Singleton
代码部分
cs
/// <summary>
/// 纯C#单例基类
/// 不需要挂载到GameObject上,可以直接调用
/// </summary>
public class Singleton<T> where T : class, new()
{
private static T _instance;
private static readonly object _lock = new object();
public static T Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new T();
}
}
}
return _instance;
}
}
protected Singleton() { }
}
总结
本文的MonoSingleton与Singleton说明
MonoSingleton<T> 特点:
- 需要挂载到GameObject上,继承MonoBehaviour
- 线程安全的懒加载模式
- 需要手动选择处理场景切换时的持久化(DontDestroyOnLoad)
- 防止重复实例创建
- 应用退出时的安全处理
Singleton<T> 特点:
- 纯C#类,不需要挂载到GameObject
- 线程安全的懒加载模式
- 可以直接调用,无需场景依赖
- 适合数据管理、配置管理等不需要MonoBehaviour生命周期的功能
都是很经典的框架,不多做说明