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

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

相关推荐
DaLiangChen6 小时前
Unity 实时 CPU 使用率监控
unity·游戏引擎
cyr___10 小时前
Unity教程(二十四)技能系统 投剑技能(中)技能变种实现
学习·游戏·unity·游戏引擎
Humbunklung12 小时前
C# WPF 实现读取文件夹中的PDF并显示其页数
pdf·c#·wpf·npoi·gemini·itext
时光追逐者12 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 48 期(2025年7.21-7.27)
c#·.net·.netcore·.net core
蓝点lilac13 小时前
C# 调用邮箱应用发送带附件的邮件
c#·.net
工程师00714 小时前
C#多线程,同步与异步详解
开发语言·c#·多线程·同步·异步编程
“αβ”14 小时前
线程安全的单例模式
linux·服务器·开发语言·c++·单例模式·操作系统·vim
蝸牛ちゃん14 小时前
设计模式(六)创建型:单例模式详解
单例模式·设计模式·系统架构·软考高级
小乖兽技术16 小时前
在 .NET 中使用 Base64 时容易踩的坑总结
开发语言·c#·.net
星星火柴93617 小时前
开发笔记 | 实现人物立绘的差分效果
笔记·unity·游戏程序·优香