18.Unity避免内存泄漏
18.1 题目
如何在Unity当中避免内存泄漏的性能问题?
18.2 深入解析
总体思路是:不再使用的对象与资源不要被长期引用(事件、静态容器、闭包、Unity 资源句柄等):
及时释放资源:
- 使用
Resources.UnloadAsset或AssetBundle.Unload清理不再使用的资源(如纹理、模型等)。 - 对于
AssetBundle,明确指定unloadAllLoadedObjects参数,确保资源彻底释放。
- 使用
委托与事件管理:
- 注册委托和事件时,必须在对象销毁前反注册(如
someEvent -= MyMethod)。 - 避免静态委托持有对象引用,导致对象无法被GC回收。
- 注册委托和事件时,必须在对象销毁前反注册(如
断开引用链:
- 对象不再使用时,将其置为
null(如myObject = null),帮助GC识别可回收对象。 - 对于集合类型(如
List<T>、Dictionary<TKey, TValue>),在清空元素后调用Clear()并置为null。
- 对象不再使用时,将其置为
利用Unity内置API:
- 适时调用
Resources.UnloadUnusedAssets()释放未被引用的资源(注意:该操作会触发GC,可能导致卡顿)。 - 使用
GC.Collect()主动触发垃圾回收(仅在必要时使用,如场景切换后)。
- 适时调用
静态对象管控:
- 减少静态对象的使用,尤其是持有大量数据的静态集合或单例。
- 静态对象生命周期结束时,手动清理其引用(如
Singleton.Instance = null)。
内存池优化:
- 频繁创建/销毁的对象(如子弹、粒子)使用对象池复用,避免重复GC压力。
- 实现自定义内存池时,确保对象回收时重置状态并断开外部引用。
避免隐式引用:
- 闭包(Lambda表达式)会隐式捕获外部变量,可能导致对象无法释放(如
StartCoroutine(() => { ... }))。 - 优先使用静态方法或局部变量,减少闭包对外部对象的引用。
- 闭包(Lambda表达式)会隐式捕获外部变量,可能导致对象无法释放(如
纹理与内存压缩:
- 使用合适的纹理格式(如ETC、ASTC)降低内存占用。
- 大纹理可通过
Texture2D.Resize()动态调整分辨率。
场景切换优化:
- 加载新场景前,确保当前场景的资源已释放(如调用
SceneManager.UnloadSceneAsync())。 - 使用
Addressables系统管理资源加载,自动处理依赖关系和卸载逻辑。
- 加载新场景前,确保当前场景的资源已释放(如调用
监控与分析工具:
- 使用Unity Profiler监控内存使用情况,定位内存泄漏点。
- 通过Memory Profiler分析堆快照,识别大对象和未释放的资源。
总结:合理的内存管理需要从代码设计(如委托管理、对象池)、资源加载(如AssetBundle)到引擎API调用(如GC触发)全方位把控,避免“内存僵尸”现象,提升游戏性能和稳定性。
18.3 答题示例
在 Unity 中避免内存泄漏,关键是及时释放不再使用的资源和引用:
及时卸载资源
- 对通过
Resources.Load加载的 Asset,使用Resources.UnloadAsset;- 对通过 AssetBundle 加载的资源,使用
AssetBundle.Unload(true);- 在场景切换后,可调用
Resources.UnloadUnusedAssets()回收未引用的资源。管理事件与委托
- 在注册事件或委托后,务必在对象销毁时用
-=注销,避免事件链持有过期引用。避免持久性引用
- 不要滥用静态字段或单例保存大量临时对象;
- 使用对象池(Object Pool)重复利用对象,而不是频繁创建销毁。
清理组件与 GameObject
- 调用
GameObject.Destroy或DestroyImmediate移除不再需要的对象;- 在销毁后将相关引用置为
null,方便 GC 判定可回收。通过以上措施,确保不再使用的资源和对象都能被及时卸载和回收,从而避免内存泄漏带来的性能问题。
18.4 关键词联想
- 资源卸载(Resources.UnloadAsset / AssetBundle.Unload)
- UnloadUnusedAssets
- GameObject.Destroy / DestroyImmediate
- 事件取消订阅(-=)
- 静态字段泄漏
- 对象池(Object Pool)
- 引用置空(null)
- 垃圾回收触发(GC)
- 内存泄漏与内存抖动
- Profiler 内存模块
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com