记录部分Unity性能优化知识
1 GC优化
GC (Garbage Collector)负责自动管理内存。当堆上的某个对象从任何GC Roots(包括栈、静态变量等)出发都不可达时,该对象会被标记为垃圾。GC会在特定时机(如内存分配预算达到阈值)执行回收,并视情况重新整理(压缩)堆内存以释放空间。
然GC是一个极其消耗性能的工作,每次都需要遍历整个堆内存,因此我们要尽量避免GC。
如何避免频繁触发GC
——减少频繁分配内存
1 | void Update(){ |
像上面这种写法,每帧都在使用new进行内存分配,我们完全可以改成下面这种写法:
1 | private List<int> list = new List<int>(); |
这种写法只有在容器被创建或扩容时才会有堆分配,从而减少了垃圾的产生。
——运用对象池
在运行时大量对象的创建和销毁依然会引起GC问题,用对象池技术可以让对象复用而不是重复的创建和销毁。
——字符串
在C#中,String是引用类型,它的值是不可变的,一旦被初始化后就不能改变其内容,频繁的修改字符串建议使用StringBuilder。
——装箱
值类型转换为引用类型的过程称为装箱,装箱会产生GC。
——协程
避免yield return 0,因为会产生GC,因为int类型的0被装箱,而使用yield return null替代则不会产生装箱操作,还比如在协程中避免多次new同一个WaitForSeconds对象。
1 | while(!isComplete){ |
——Linq表达式
LINQ和正则表达式由于在后台会有装箱操作而产生垃圾,在有性能要求的时候最好不使用。
2 Draw Call优化
在Unity里,Draw Call指的是CPU发出的绘制请求,其中包含了绘制所需的所有信息,如纹理信息、着色器等。
为什么我们要优化Draw Call?
在现代硬件中,GPU的处理能力通常很强,假设一个场景有2000个Draw Call,CPU可能需要花20ms才能把这些指令发完,而GPU画完它们只需要5ms。也就是说,Draw Call太多的后果是GPU大部分时间都在等CPU发指令,这时游戏帧率就会卡在CPU提交这一步。
Draw Call的优化手段:批处理技术。