Unity 性能优化
GC
- 减少垃圾数量
- 使用缓存:避免内存重复、重新分配
- 减少在
Update
这种频繁调用的方法中分配内存
- 使用
Clear
清理集合,而不是每次生成
- 善用对象池
- 减少不必要的堆内存分配
String
是不可变的,每次更改都是创建一个新的对象
- 将常用字符串缓存
- 对于频繁更新的
Text
组件应该把其中变化和不变化的部分分开
- 对于频繁更新的字符串,使用
StringBuilder
替代
- 移除
Debug.Log()
- 避免
Unity
方法不恰当调用
- 返回数组的方法,会创建新的数组,应在反复使用前缓存
- 使用
CompareTag
替代 gameObject.tag
- 使用
Input.GetTouch
和 Input.touchCount
替代 Input.touches
- 使用
Physics.SphereCastNonAlloc
替代 Pysiscs.SphereCastAll
- 装箱:把值类型变量当引用类型使用,将创建一个临时
Object
封装值类型变量
Object.Eauals
方法参数是 Object
,如果传入 int
或 float
,则会产生装箱
String.Format
同上
- 就算我们自己代码中避免装箱,插件中也可能发生装箱,应移除这些方法的调用
Coroutines
StartCoroutine
产生少量垃圾(堆内存分配),因为 Unity
需要创建实例来维护
- 减少在性能敏感处调用
StartCoroutine
;避免嵌套调用,可能导致调用延迟
yield return 0
会导致装箱,使用 null
代替
- 提前缓存
new WaitForSeconds()
对象,复用
- 如果
coroutine
产生太多垃圾,使用 Undate
或消息机制替代 coroutine
- 方法引用
- 在
Unity
中,匿名方法、命名方法的引用是一个引用类型变量,产生堆分配
- 闭包会显著增加内存占用和堆分配,因为捕获了临时变量
- 在
gameplay
中避免使用匿名函数、闭包
- 避免使用
LINQ
、正则表达式,因为都会产生装箱
- 从代码架构上避免不必要的
GC
检测
struct
不要包含引用类型字段,这会导致检测所有字段
- 类中减少不必要的引用字段
物理
- 减少射线频率、长度、layer
- 善用 Physics Matrix
- 不要移动静态
Collider
,需要移动的话加 RigidBody
- 尽量使用简单的
Collider
替代 MeshCollider
;不同类型进行碰撞检测的相对成本是按照以下顺序排列的,从最耗费资源到最不耗费资源:三角形网格、凸包(三角形网格)、胶囊体、球体、立方体、平面、点
- 控制好
FixedUpdate
的频率,1s 建议不要执行超过30次,因为 FixedUpdate
执行 Physics
,如果Update
卡顿会导致 FixedUpdate
执行多次,继而 Update
更加卡顿,形成恶性循环
动画
- 文件压缩,去除无用通道,比如
Scale
,降低精度保存两位有效小数,设置数值范围压缩数据等
- GPU 加速动画播放
- 开启 Unity 的优化选项
- 减少关键帧