Unity 单例模式完全指南

大家好!我是 数擎 AI,一位热爱探索新技术的前端开发者,在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情,欢迎关注我的文章,我们一起成长、进步!
开发领域 :前端开发 | AI 应用 | Web3D | 元宇宙
技术栈 :JavaScript、React、ThreeJs、WebGL、Go
经验经验 :6 年+ 前端开发经验,专注于图形渲染和 AI 技术
开源项目AI 智简未来晓智元宇宙数字孪生引擎

一、什么是单例模式?

单例模式(Singleton Pattern) 是一种常用设计模式,核心思想是:

一个类只有一个实例,并提供一个全局访问点。

适用场景:

在游戏开发中,通常用于:

  • 🎵 AudioManager(音频管理)
  • 🎮 GameManager(游戏控制)
  • 🧠 DataManager(数据持久化)
  • 🖼 UIManager(界面逻辑)
  • 🗺 SceneManager(场景切换)

二、Unity 与单例的"冲突"

Unity 的 MonoBehaviour 无法用传统 C# 单例写法(new 关键字)创建实例:

限制 说明
不能使用 new MonoBehaviour 由 Unity 引擎托管
必须挂在 GameObject 上 无法脱离场景生命周期
多场景可能重复实例 场景加载可能重复创建组件实例

三、MonoBehaviour 单例实现方案

✅ 推荐写法(最通用)

csharp 复制代码
public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject); // 防止重复实例
            return;
        }

        Instance = this;
        DontDestroyOnLoad(gameObject); // 场景切换不销毁
    }
}


### 使用方式:
```csharp
GameManager.Instance.DoSomething();

核心要点:

  • 使用 Awake() 初始化,确保运行时唯一
  • 使用 DontDestroyOnLoad 保持全局可访问性
  • 在有旧实例时销毁当前 GameObject(或反之)

四、泛型单例基类(进阶封装)

csharp 复制代码
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    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("[Singleton] 已销毁,将不再创建实例:" + typeof(T));
                return null;
            }

            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = FindObjectOfType<T>();
                    if (_instance == null)
                    {
                        GameObject singletonObject = new GameObject(typeof(T).Name);
                        _instance = singletonObject.AddComponent<T>();
                        DontDestroyOnLoad(singletonObject);
                    }
                }
                return _instance;
            }
        }
    }

    protected virtual void OnDestroy()
    {
        _applicationIsQuitting = true;
    }
}

示例继承:

csharp 复制代码
public class AudioManager : Singleton<AudioManager>
{
    public void PlaySound(string clipName)
    {
        // 实现播放逻辑
    }
}

五、常见陷阱 ⚠️

陷阱 说明
❌ 多个场景创建多个实例 应用 DontDestroyOnLoad 并检测重复
❌ 在 OnDestroy 后再次访问 应避免退出时访问 Instance
❌ 静态实例未初始化 Unity 生命周期复杂,可能在未执行 Awake() 时访问 Instance

六、非 MonoBehaviour 单例(纯逻辑类)

适用于工具类、算法类等无需挂载到场景的:

csharp 复制代码
public class ConfigManager
{
    private static ConfigManager _instance;
    public static ConfigManager Instance => _instance ?? (_instance = new ConfigManager());

    private ConfigManager()
    {
        // 私有构造函数
    }
}

七、总结

类型 是否 MonoBehaviour 是否跨场景切换 是否自动创建
简单单例 ✅ 是 ✅ 是 ❌ 否(需手动挂载)
泛型单例 ✅ 是 ✅ 是 ✅ 是(自动创建)
纯逻辑单例 ❌ 否 ✅ 是 ✅ 是(自动创建)

✅ 建议:

  • 管理 UI、音频、数据等组件时使用 MonoBehaviour 单例;
  • 工具类使用普通 C# 单例;
  • 多场景中必须使用 DontDestroyOnLoad 配合检测重复。

八、附加建议与思考 💡

Service Locator 模式 有时比单例更灵活,适合大项目。

避免过度使用单例,否则可能造成依赖过强、测试困难。

Unity 2021+ 支持 ScriptableObject + Addressable 实现配置数据全局共享,也是替代方案之一。

结语

在 Unity 中掌握单例模式,不仅是对设计模式的理解,更是构建 可维护、可扩展、高内聚系统架构 的关键一步。

相关推荐
AI多Agent协作实战派21 分钟前
AI多Agent协作系统实战(二十三):Agent读HEARTBEAT.md不读AGENTS.md——openclaw的文件加载之谜
前端·数据库·人工智能·uni-app
2601_955760071 小时前
如何用 Claude Opus 5 API 批量扩展长尾关键词和文章选题
前端·python·搜索引擎
KaMeidebaby1 小时前
卡梅德生物技术快报|bli亲和力检测gst:告别批量跑胶:BLI实时酶切监测技术加速GST融合蛋白下游流程优化
前端·网络·数据库·人工智能·算法
触底反弹2 小时前
🚀 删了数据刷新又回来?3 组件 × 4 回调 × 3 坑讲透 React 父子通信
前端·javascript·react.js
耳东小鹿3 小时前
对象常用方法
前端
程序员海军3 小时前
一个 AI 应用开发程序员的一天,都在屏幕前忙些什么?
前端·后端·程序员
程序员黑豆3 小时前
鸿蒙应用开发:Stack堆叠组件实战——实现微信消息角标效果
前端·harmonyos
夏幻灵3 小时前
浏览器原理深度解析:从输入 URL 到页面展现的全流程剖析
前端
闲猫4 小时前
Agent工程实践:从WorkFlow到多Agent协作的落地笔记
java·服务器·前端
带娃的IT创业者4 小时前
重新定义前端构建速度:深度解析 SWC 如何用 Rust 颠覆 JavaScript 工具链
前端·javascript·rust·前端构建·swc