静态变量引用GameObject切换场景后为何出现内存异常?
问题原因分析
核心矛盾:静态变量变null≠对象无引用
你遇到的情况本质是Unity场景卸载的标记逻辑和实际内存引用的脱节:
静态变量变null的原因:Unity在卸载场景时,会把所有未标记
DontDestroyOnLoad的场景内GameObject标记为"待销毁",此时这些对象的Unity Object引用会被自动置为null(这是Unity对销毁对象的特殊处理,避免无效访问),但这只是Unity的内部标记,不代表对象已经被GC回收。内存未释放的关键:隐式引用残留
真正导致对象无法被GC回收的是你没注意到的其他强引用,常见场景包括:- 未取消的委托/UnityEvent订阅:比如按钮的
onClick还挂着该对象的方法、自定义委托还持有对象的回调引用 - 未终止的协程:协程会持有所属对象的引用,只要协程还在运行,对象就会被保留
- 内部模块的引用:比如动画系统还在播放该对象的动画、粒子系统的残留效果、UI画布的层级引用等
- 第三方插件的隐式持有:部分插件会自动缓存对象引用,未在场景卸载时清理
- 未取消的委托/UnityEvent订阅:比如按钮的
GC的延迟性:即使对象已经没有任何引用,Unity的GC也不会立刻执行回收——默认会在内存分配达到阈值时自动触发,或者需要手动调用
GC.Collect()才会强制执行。
排查与解决步骤
- 检查隐式引用:
在对象的OnDestroy()方法里做清理:取消所有委托订阅、停止协程、清空UnityEvent绑定;也可以用Unity的Profiler(Memory模块)查看对象的引用链,找到残留的引用来源。 - 验证GC效果:场景切换后手动执行
GC.Collect(); GC.WaitForPendingFinalizers();,如果内存释放了,说明是GC延迟问题;如果没释放,继续排查残留引用。 - 规范静态变量处理:在场景卸载回调(比如
SceneManager.sceneUnloaded)里主动将静态变量置为null,避免自己的代码留下无效引用。
内容的提问来源于stack exchange,提问作者Wiseak
相关产品推荐
相关产品推荐

