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

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

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

相关推荐
警醒与鞭策12 分钟前
【无标题】
android·unity·性能优化·游戏引擎·perforce
zhchyun20082 小时前
【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(10)
ui·unity·游戏引擎
波力海苔夹心脆6752 小时前
C# 序列化与反序列化详解:System.Text.Json、Newtonsoft.Json、XmlSerializer 用法、特性选项与安全实践
经验分享·后端·c#·json·.net
地狱为王6 小时前
Unity使用NVIDIA的Audio2Face驱动口型
unity·游戏引擎
小羊没烦恼!7 小时前
在Scrum中实施敏捷建模
java·开发语言·windows·算法·c#
Lost of 程序猿8 小时前
建造者模式实战:告别“十参数构造函数“的数据导出任务
后端·设计模式·c#·asp.net
ebiobiz8 小时前
STM32F4 Unity 单元测试与多次测试失败率统计详细步骤
stm32·unity·单元测试
mudtools10 小时前
在.NET现有系统中快速集成飞书任务分配能力
后端·c#·.net
工具派13 小时前
Word文档太大怎么拆分?段落结构与两种拆法的边界实测
开发语言·c#·word
潜龙952713 小时前
需求文档一键变测试用例:手工用例智能生成平台
开发语言·c#