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

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

相关推荐
Ray Liang13 小时前
用六边形架构与整洁架构对比是伪命题?
java·python·c#·架构设计
Scout-leaf4 天前
WPF新手村教程(三)—— 路由事件
c#·wpf
用户298698530144 天前
程序员效率工具:Spire.Doc如何助你一键搞定Word表格排版
后端·c#·.net
mudtools5 天前
搭建一套.net下能落地的飞书考勤系统
后端·c#·.net
玩泥巴的5 天前
搭建一套.net下能落地的飞书考勤系统
c#·.net·二次开发·飞书
唐宋元明清21885 天前
.NET 本地Db数据库-技术方案选型
windows·c#
lindexi5 天前
dotnet DirectX 通过可等待交换链降低输入渲染延迟
c#·directx·d2d·direct2d·vortice
qq_454245035 天前
基于组件与行为的树状节点系统
数据结构·c#
爱搞虚幻的阿恺5 天前
Niagara粒子系统-超炫酷的闪电特效(加餐 纸牌螺旋上升效果)
游戏·游戏引擎
bugcome_com5 天前
C# 类的基础与进阶概念详解
c#