Unity 减少垃圾收集 (GC) 的影响

Unity 使用 Boehm-Demers-Weiser 垃圾收集器,它会停止运行程序代码,并且仅在其完成所有工作后才恢复正常执行。
要注意某些不必要的堆分配,这可能会导致 GC 尖峰 :

1.字符串 :

在 C# 中,字符串是引用类型,而不是值类型。减少不必要的字符串创建或操作。避免解析基于字符串的数据文件,例如 JSON 和 XML ;改用 ScriptableObject 或 MessagePack、Protobuf 等格式存储数据。如果需要在运行时构建字符串,请使用 StringBuilder 类。

2.Unity 函数调用 :

请注意,某些函数会创建堆分配。缓存数组引用,不要在循环中分配数组。此外,请使用某些避免产生垃圾的函数 ;例如,使用 GameObject.CompareTag 而不是手动将字符串与 GameObject.tag 进行比较
(返回新字符串会产生垃圾)。

3.装箱 :

避免传递值类型变量来代替引用类型变量。这会创建临时对象,以及随之而来的潜在垃圾,例如,int i = 123; object o = i 会将值类型隐式转换为类型对象。

4.协程 :

虽然 yield 不会产生垃圾,但创建新的 WaitForSeconds 对象会。缓存并重用 WaitForSeconds 对象,而不要在 yield 行中创建它。

5.LINQ 和正则表达式 :

它们幕后都会进行装箱,从而产生垃圾。如果性能很重要,请避免使用 LINQ 和正则表达式。如有可能,定时收集垃圾
如果确定垃圾收集冻结不会影响游戏中的某个特定点,则可以使用 System.GC.Collect
触发垃圾收集。
有关在哪些地方可以通过这样做而受益的示例,请参阅了解自动内存管理。
使用增量式垃圾收集器拆分GC 工作负载
增量式垃圾收集使用多个短得多的程序执行中断,而不是单次长时间的中断,将工作负载分布到多个帧上。如果垃圾收集影响了性能,可以尝试启用该选项,看看它能否显著减少 GC 尖峰问题。使用 Profile Analyzer 验证对应用程序的改善。

### Unity 引擎中的垃圾回收机制 #### 工作原理 Unity 使用 Mono 或 IL2CPP 进行脚本编译和执行,在这两种模式下,垃圾回收(Garbage Collection, GC)都是自动化的。GC 主要负责释放不再使用的对象所占用的内存资源。 - **Mono 模式的垃圾回收** 在 Mono 模式中,Unity 默认采用 Boehm-Demers-Weiser (BDW) 垃圾收集器[^1]。该收集器是一种保守型的标记清除算法,其基本流程如下: - 扫描堆栈、寄存器以及全局变量来寻找根集(Root Set),即可能指向存活对象的地方。 - 对找到的对象进行遍历并打上标记表示它们仍然活跃。 - 清理未被标记的对象,并调整指针使剩余空间连续化以便后续分配新对象时更高效。 - **IL2CPP 模式的垃圾回收** 当使用 IL2CPP 编译方式时,则会切换至基于可达性的精确垃圾收集方案[^3]。此方法通过分析程序运行期间的实际引用关系图谱来进行更加精准的记忆体管理操作;相比起传统的保守式做法可以减少不必要的扫描范围从而提高效率。 ```csharp // C# 示例:创建大量临时对象可能会触发频繁的垃圾回收 for(int i=0; i<1000000; ++i){ var tempObj = new GameObject(); // 不推荐的做法 } ``` #### 优化建议 为了降低因不合理的代码逻辑而导致过多无谓的垃圾回收活动发生频率,可以从以下几个方面着手改进: - 尽量重用已存在的对象而非不断实例化新的实体; - 减少局部变量声明次数特别是循环体内; - 利用 Object Pooling 技术预先准备好一批可重复利用的游戏组件池子供即时调取而不必每次都重新构建; - 避免在 Update 方法内做复杂的计算或数据结构复制动作因为这往往伴随着大量的短期生存期的小物件诞生与消亡过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值