Unity 性能优化

Unity 性能优化

GC

  • 减少垃圾数量
    • 使用缓存:避免内存重复、重新分配
    • 减少在 Update 这种频繁调用的方法中分配内存
    • 使用 Clear 清理集合,而不是每次生成
    • 善用对象池
  • 减少不必要的堆内存分配
    • String 是不可变的,每次更改都是创建一个新的对象
      • 将常用字符串缓存
      • 对于频繁更新的 Text 组件应该把其中变化和不变化的部分分开
      • 对于频繁更新的字符串,使用 StringBuilder 替代
      • 移除 Debug.Log()
    • 避免 Unity 方法不恰当调用
      • 返回数组的方法,会创建新的数组,应在反复使用前缓存
      • 使用 CompareTag 替代 gameObject.tag
      • 使用 Input.GetTouchInput.touchCount 替代 Input.touches
      • 使用 Physics.SphereCastNonAlloc 替代 Pysiscs.SphereCastAll
    • 装箱:把值类型变量当引用类型使用,将创建一个临时 Object 封装值类型变量
      • Object.Eauals 方法参数是 Object,如果传入 intfloat,则会产生装箱
      • 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 的优化选项
  • 减少关键帧
top