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

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

相关推荐
懒人咖20 小时前
缺料分析时携带用料清单的二开字段
c#·金蝶云星空
在路上看风景20 小时前
4.5 顶点和片元
unity
bugcome_com20 小时前
深入了解 C# 编程环境及其开发工具
c#
wfserial1 天前
c#使用微软自带speech选择男声仍然是女声的一种原因
microsoft·c#·speech
阔皮大师1 天前
INote轻量文本编辑器
java·javascript·python·c#
kylezhao20191 天前
C# 中的 SOLID 五大设计原则
开发语言·c#
啦啦啦_99991 天前
Redis-5-doFormatAsync()方法
数据库·redis·c#
Porco.w1 天前
C#与三菱PLC FX5U通信
网络·c#
E_ICEBLUE1 天前
PPT 批量转图片:在 Web 预览中实现翻页效果(C#/VB.NET)
c#·powerpoint·svg
JQLvopkk1 天前
C# 轻量级工业温湿度监控系统(含数据库与源码)
开发语言·数据库·c#