Unity 性能优化:Animator 调用与内存管理
问题一:Animator 调用次数过多及 Culling 设置
Q: 现在动画的 Culling Mode 是 Cull Update Transforms,不过从 Scene 窗口来看,在屏幕外的动画还是在动,这个还需要做其他的什么设置吗?为什么报告里 Animator 的调用次数那么多呢?
A:
- Scene 窗口显示影响:Scene 窗口内的显示确实会影响观察结果。要准确判断实际运行状态,需要关闭 Scene 窗口。
- Occlusion Culling 设置:Camera 没有勾选 Occlusion Culling 通常不影响 Animator 的调用统计。
- Profiler 排查方法:在 Profiler 里面选择
Animator.ApplyOnAnimatorMove函数,然后打开 Related Data,可以看到具体是哪些对象触发了调用。
问题二:UI 相关堆内存对象和纹理资源未释放
Q: 项目中发现一些 UI 图片被大量 UI 对象引用,但这些对象应该已经在代码中调用销毁了,但看起来 RUUA 和 GC 都没起到作用,这最终导致项目中很多 UI 相关堆内存对象和纹理资源都占用了较大内存没有释放。可能是什么原因?
A: 此问题通常由隐性引用、资源标志位或原生资源未释放导致。建议按以下步骤排查:
- 排查代码引用链:检查 Lua 或 C# 中的静态变量、事件监听、闭包是否持有 UI 对象引用,导致 GC 无法回收。查看 GOT Online 报告的 Mono 引用对象统计,若'Destroyed 对象数量'持续上涨,说明存在 Lua 端未解引用,需及时释放引用链。
- 检查资源标志位:若纹理或对象被标记为
HideFlags.DontUnloadUnusedAsset,Resources.UnloadUnusedAssets将无法卸载它们。需检查代码是否误设该标志,必要时使用DestroyImmediate手动清除。 - 确认 AssetBundle 与图集依赖:若引用图集的 AssetBundle 未完全卸载,图集会驻留。确保
AssetBundle.Unload(true)调用正确,或尝试Resources.UnloadAsset。 - 排查原生资源:RenderTexture 不会自动垃圾回收,使用后必须调用 Release 释放硬件资源,否则会造成显存与内存泄漏。
- 考虑内存碎片:堆内存高未必是对象未卸载,可能是碎片过多。排查
byte[]、MemoryStream等频繁分配对象,使用对象池优化。
建议结合内存快照分析具体占用对象,定位引用源,必要时手动管理资源生命周期,避免过度依赖自动卸载机制。
问题三:Destroyed 对象数较高且持续上涨的含义
Q: 看了 UWA 报告中的 Mono 引用对象统计页面,Destroyed 对象数确实较高且有上涨,这个具体是什么含义?
A: Destroyed 对象数较高且持续上涨是 Mono 堆内存泄漏的重要预警信号,具体含义如下:
- 定义说明:Destroyed 对象指在 C# 端已调用 Destroy 销毁,但 Lua 端仍持有引用的 Mono 层对象。这些对象虽在场景中已被移除,但因 Lua 端未解引用,仍占用堆内存无法被 GC 回收。
- 产生原因:Lua 访问 Unity 对象时,会通过 Wrapper 代码将对象引用存入容器,以确保 C# 端 GC 不会提前回收。若 Lua 端未及时释放这些引用,C# 端的 Destroy 操作无法彻底清理内存,导致对象驻留。
- 持续上涨的风险:若 Destroyed 对象数量持续上涨,说明 Lua 端引用链未正确清理,Mono 堆内存会不断累积,最终导致内存占用持续增长、GC 频率升高引发卡顿,极端情况下导致内存溢出闪退。
- 排查建议:


