GC的功能:对标记为未使用的内存进行回收,这个过程还会对余下的对象进行标记分级,内存整合。

GC的产生:堆分配时堆上的可用内存不足时触发GC,根据GC的机制。只要我们申请对堆内存,就可能 触发GC.

GC的影响:GC需要检查堆上的对象是否有效,如果检查的对象很多将费时费力。这导致游戏卡顿或缓慢运行

Unity中会申请堆内存的情况

  1. new 对象
  2. 容器扩容时,如List、Dictionary
  3. 启用协程时
  4. 生成闭包时
  5. 某个函数返回数组、List等容器对象时
  6. 字符串拼接时
  7. IO时
  8. 装箱时
  9. GameObject.tag、GameObject.name
  10. 使用变长参数数组
  11. 发生UGUI重构
  12. 还有一些插件内部堆内存申请

如何避免上面的这些情况

  1. 针对new class()

可以考虑用struct代替,如果只是数据的存储

如果不行,且频繁创建可以考虑缓存起来,或者使用static,弄对象池等。

2.针对容器扩容

应该减少容器扩容的次数

对容器进行初始化设置容量(初始值大小要看实际情况)

List使用AddRange()代替Add()

Dictionary扩容按HashHelpers类中的primes数组走

3.启用协程时

每次StartCoroutine都会生成一个对象

协程内部使用的临时变量越多,GC就越高

所以===》

频繁创建的协程考虑使用Update替代

减少协程内部临时变量的使用

对new WaitForEndOfFrame() 、new WaitForSeconds(1.0f)等进行统一 cache

使用第三方插件,如MEC

4.生成闭包时

尽可能避免匿名函数引用外部变量,让其可被静态化

搞清楚哪些变量被匿名函数引用了,防止内存泄漏

尽量把被引用的变量声明放在后面,用变量复制来延迟匿名函数创建

尽量不用Linq语句

5.函数返回数组、List等容器对象时

减少调用频率,如下




unity gpu性能优化 unity优化gc_unity gpu性能优化


unity gpu性能优化 unity优化gc_Powered by 金山文档_02


使用传入代替返回,如下


unity gpu性能优化 unity优化gc_List_03


unity gpu性能优化 unity优化gc_List_04


6.字符串拼接时

可以将动态文字与静态文字进行分离使用

减少拼接次数

重复使用一个字符串拼接,考虑用stringbuilder

7.IO时

对资源进行缓存使用

8.装箱时

1、降低数值类型转string类型

2、Enum或 struct作为 Dictionary的 Key,或List的元素,

在List的Contains()、Dictionary的ContainKey()时,会触发Equals造成装箱,解决

对于struct,override GetHashCode并实现 IEquatable<T>

对于Enum,直接使用int

或者Enum在作为Dictionary Key时,为Enum定义一个专用比较器。如下


unity gpu性能优化 unity优化gc_Powered by 金山文档_05


unity gpu性能优化 unity优化gc_c#_06


9.使用GameObject.Tag

使用CompareTag()代替

10.函数使用变长参数传参

函数传参时,使用可变参数传参会自动转换成 params Type[] args,所以最好的建议是不用

11.UGUI网格重建时

UI动静分离

12.一些插件内部堆内存申请

使用插件前,先用Profiler跑跑看,有没有GC产生