Unity WebGL 运行时优化建议
收藏
我的收藏Unity WebGL使用 IL2CPP 的技术,接受 .NET 字节码(C#脚本)并将其转换为相应的 C++ 源文件,然后使用 emscripten 编译器工具链将C++代码编译为 wasm 文件,wasm文件能够直接在浏览器环境中运行。
由于Unity WebGL最终运行在虚拟机环境里,且目前不支持多线程,测试发现Unity WebGL方案的性能是原生的1/3左右,因此针对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的优化可以参考
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内置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,可以参考文档
3.1 限制分辨率
可调用对应的C#接口修改为较低的分辨率
3.2 启用WebGL2.0
- •WebGL2.0支持延迟渲染,可能会对多光源场景有较大优化。
- •WebGL2.0支持GPU Instancing,可以进一步合并DrawCall。
3.3 SRP Batcher
SRP Batcher只能运行在WebGL2.0上
SRP Batcher将材质信息持久化存在显存中,同时批量处理了两个DrawCall之间的绑定操作,大大减少了CPU的消耗,更多信息可以参考官方文档
3.3 URP优化
参考 https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/CustomURP.md