抖音开放平台Logo
开发者文档
控制台

Unity WebGL 运行时优化建议

收藏
我的收藏
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优化