You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity单例模式去重:Destroy(gameObject)必要性与重复实例成因

Unity MonoBehaviour单例实现问题解析

Unity开发中常使用单例模式实现跨场景全局唯一的管理对象,基于MonoBehaviour的典型GameManager.csAwake生命周期实现代码如下:

private void Awake()
{
    // 检查实例是否为空,为空则将当前对象设为全局单例
    if (instance == null) {
        instance = this;
        // 标记游戏对象,切换场景时不做销毁
        DontDestroyOnLoad(gameObject);
    } else {
        Destroy(gameObject);
    }
}  

针对这段实现的两个核心疑问解答如下:

1. Destroy(gameObject)语句的必要性

这行是保证单例唯一性的核心兜底逻辑,缺了它单例的全局唯一约束就会直接失效。
第一个被创建的GameManager实例会给静态instance变量赋值,加上DontDestroyOnLoad标记后会常驻整个游戏生命周期。如果后续流程中生成了新的同类型实例,这行代码会直接销毁新生成的重复对象,避免场景中同时存在多个同类型管理器。
不少开发者写单例时漏写这行,运行一段时间后场景里堆积了多个同类型管理器,引发事件重复触发、全局状态错乱、存读档数据覆盖等很难排查的问题,本质就是缺少重复实例销毁的兜底处理。

2. 运行时出现第二个同类型实例的常见原因

MonoBehaviour是由Unity引擎托管生命周期的组件,无法像普通C#类那样通过私有化构造函数完全禁止外部创建实例,出现重复实例基本都是以下几种场景:

  • 多场景重复挂载:多个场景中都预先放置了挂载GameManager脚本的对象。初始场景加载时生成第一个常驻的单例对象,后续切换到其他带同脚本对象的场景时,Unity会自动加载场景内的预置对象,生成第二个实例。
  • 运行时非法创建:代码逻辑中存在动态Instantiate挂载GameManager脚本的预制体、或者主动调用AddComponent<GameManager>()的逻辑,且创建前没有做单例存在性校验,就会生成额外的重复实例。
  • 编辑器环境特殊问题:编辑器下运行游戏时,如果修改脚本触发C#域重载、或者退出播放模式时静态变量没有被正确回收,下次进入播放模式可能出现旧实例残留+新实例生成的重复情况,这类问题仅会在编辑器环境出现,真机运行不会触发。

内容的提问来源于stack exchange,提问作者Dylariant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 23:15:45