抖音开放平台Logo
开发者文档
“/”唤起搜索
控制台
  • 开发指南
  • 游戏引擎
  • 基础能力
  • 开放能力
  • 性能优化
  • Unity 小游戏性能优化
  • 性能优化总览
  • 启动性能
  • 运行性能
  • 优化Unity WebGL的内存
  • 开发阶段内存调优
  • Unity WebGL 运行时优化建议
  • WebGL2.0渲染支持说明
  • 优化Unity WebGL的渲染性能
  • iOS Metal 渲染模式
  • 普通小游戏性能优化
  • 安全指引
  • Unity WebGL使用 IL2CPP 的技术,接受 .NET 字节码(C#脚本)并将其转换为相应的 C++ 源文件,然后使用 emscripten 编译器工具链将C++代码编译为 wasm 文件,wasm文件能够直接在浏览器环境中运行。
    由于Unity WebGL最终运行在虚拟机环境里,且目前不支持多线程,测试发现Unity WebGL方案的性能是原生的1/3左右,因此针对Unity WebGL方案的优化非常重要。
    开发者应对Unity WebGL方案做出优化,以达到可以接受的流畅度标准和性能要求,具体的指标及性能基线可以参考性能评估标准
    下面给出一些常用的运行时优化建议

    一. 配置相关

    1.1 物理

    物理相关优化可以参考

    1.1.1 小建议

    以下是几个可以快速提升物理性能的建议:

    手动关闭物理模块

    如果游戏中没有使用到物理模块,应关闭Auto Simulation选项,该选项默认开启,会导致不必要的性能浪费。
    Edit->Project Settings->Physics->Auto Simulation

    调整物理计算频率
    在Unity自带的物理引擎中,物理模块运行在FixedUpdate.PhysicsFixedUpdate中,FixedUpdate的时间间隔也代表这物理模块的时间间隔
    Edit->Project Setting->Time

      Fixed Timestep:决定了FixedUpdate的更新间隔,该值越大,则间隔越大
      Maximum Allow Timestep: 该值会对FixedUpdate的执行此时进行限制
    适当调整Fixed Timestep与 Maximum Allowed Timestep降低计算频率
    选用合适的碰撞体类型
    对于物理碰撞精度要求不高时,可以考虑选用开销较低的碰撞体类型,以下是各种常用碰撞体的开销排序
    sphere Collider(最低)
    capsule Collider
    box Collider
    Mesh Collider(开销最大,且远大于前3种)

    1.1.2 性能分析与调试

      关于物理模块性能分析可以选择Unity内置Profiler
    Window->Analysis->Profiler
    参数细节可见文档
      物理调试可以选择
    Window->Analysis->Physics Debugger
    参数细节和使用相关可以参考

    1.2 UI

    关于UI的优化可以参考
    Unity官方的优化建议,从12:46开始介绍UI模块的优化

    1.2.1 使用图集

    sprite Atlas是一个图集打包工具,使用Sprite Atlas
      减少drawcall
      减少包体大小
      减少图片运行时的加载时间
    如果游戏中大量使用2DSprite,可以考虑使用(Unity - Scripting API: SpriteAtlas),可以参考Introduction to the Sprite Atlas - Unity Learn

    1.2.2 合批与Canvas重建 合批的规则可以参考:

    关于UI合批,对于同一深度,Unity会尽可能将相邻的使用相同材质和贴图的元素合批。
    Canvas重建可以参考:
    Canvas中的所有元素最终会合并成一个SharedMesh,修改 Canvas中的任意元素会导致整个Canvas重建,一个比较直接的优化方式是动静分离,即活动的元素放在一个Canvas下,不可活动的元素放在另一个Canvas下。

    1.2.3 Overdraw相关

    UI是在透明队列中渲染的,任何一个fragment都会计算所有覆盖在该fragment上的所有层级,而大多数情况下只有最上层的才是真正需要的,会导致不必要的消耗。
    对于OverDraw检测可以使用Unity内置
    Scene->Shading Mode->Overdraw
    也可以使用外部的检测工具如RenderDoc,可以参考

    1.2.4 一些配置上的小建议

      如果某个Image组件不需要与点击事件交互,那么应该关闭Raycast Target选项。
      需要Raycast交互的元素,不要放在过深的层级里面,原因是Raycast将暴力遍历根部的所有Transform层级,并要检测与Transform关联的所有组件,以寻找某个组件是否实现了ICanvasRaycastFilter。一个优化方法是在某个偏浅的节点接收Raycast,再将信息传递到某个偏深的节点。
      Text组件尽量避免开启Best Fit选项,这会导致在运行时实时计算最佳大小。
      尽量避免使用mask组件,会导致额外的drawcall,如果避免不了,可以考虑使用Rect Mask 2D,该组件不会影响合批,但是只支持矩形Mask。

    1.2.5 性能分析工具

    可以使用Unity内置Profiler,通过启用/禁用某些UI,观察性能变化情况
    Window->Analysis->Profiler
    具体参数介绍可见文档Unity - Manual: UI and UI Details Profiler
    也可以使用Unity内置Frame Debuger,其中会显示UI所包括的所用DrawCall。
    Window->Analysis->Frame Debug
    Frame Debugger相关介绍可见Unity - Manual: Frame Debugger window reference

    1.3 图片压缩设置

    图片使用ASTC格式进行压缩。(Unity2021以后的版本支持)

    二. 代码相关

    可参考

    2.1 几个常用的代码风格优化手段

      避免使用Unity某些内置方法
    GameObject.SendMessage() GameObject.BroadcastMessage() UnityEngine.Object.Find() UnityEngine.Object.FindWithTag() UnityEngine.Object.FindObjectOfType() UnityEngine.Object.FindObjectsOfType() UnityEngine.Object.FindGameObjectsWithTag() UnityEngine.Object.FindGameObjectsWithTag()
    Event等监听函数,如果无法避免,应尽量使用C#内置Event而不是UnityEvent
      善用缓存引用
    如果需要多次使用某一个Component,应在第一次获取时就将其缓存,而不是每次都现场获取
      避免空回调
    每次生命周期方法如Start(),Update() 都会导致额外的函数压栈出栈,如果某个生命周期方法里什么也没做,那么应该删除整个方法,而不是留一个空方法。
      装箱拆箱
    尽量避免使用 ArrayList等非泛型集合,尽量使用List<T>等数据类型绑定的泛型集合。

    2.2 资源加载

    Unity WebGL使用单线程,因此Addressables的资源加载和下载等异步操作最终都是运行在同一线程,因此Addressables加载会耗费大量CPU,可参考文档使用 Addressable 进行资源按需加载

    2.3 实例化

    如果需要频繁的使用Object.Instantiate()Object.Destroy()可以考虑使用对象池
    可以参考

    三. 渲染相关

    渲染的一个很重要的优化方向是减少DrawCall,可以参考文档
    其他如LOD、光照、纹理等优化方案,可以参考详细文档优化Unity WebGL的渲染性能

    3.1 限制分辨率

    可调用对应的C#接口修改为较低的分辨率

    3.2 启用WebGL2.0

      WebGL2.0支持延迟渲染,可能会对多光源场景有较大优化。
      WebGL2.0支持GPU Instancing,可以进一步合并DrawCall。
    WebGl2.0具体可见WebGL2.0渲染支持说明

    3.3 SRP Batcher

    SRP Batcher只能运行在WebGL2.0上
    SRP Batcher将材质信息持久化存在显存中,同时批量处理了两个DrawCall之间的绑定操作,大大减少了CPU的消耗,更多信息可以参考官方文档

    3.3 URP优化