Unity中的MonoSingleton<T>与Singleton<T>

发布于:2025-06-03 ⋅ 阅读:(21) ⋅ 点赞:(0)

1.MonoSingleton

代码部分

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方法

protected override void Awake()
{
    base.Awake();
    DontDestroyOnLoad(gameObject);
}

2.Singleton

代码部分

/// <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生命周期的功能

都是很经典的框架,不多做说明


网站公告

今日签到

点亮在社区的每一天
去签到