Skip to content

优化运行性能 ​

一、运行性能概述 ​

Unity WebGL 是以 WebAssebly(WASM)+WebGL 为核心的技术方案,运行性能会极大影响可承载的游戏内容玩法。

本文主要介绍 Unity WebGL 与基于 JS 引擎的普通 H5 游戏、原生 APP 手游之间技术栈导致的性能差异,以及不同系统平台(Android、iOS、Windows PC)之间的性能差异。其次阐述最佳的性能优化工具与常见优化手段。

Unity WebGL VS APP 的运行性能差异 ​

  • CPU 性能差异

Unity WebGL 是以 WASM 虚拟机的形式运行在类浏览器环境中,因此 CPU 算力会受限于虚拟机的执行效率。

Unity WebGL 目前不支持多线程,导致部分模块比如AI、动画、渲染无法得到多线程的加速。

这是导致了 Unity WebGL 与 APP 存在性能差距的最主要因素。通常而言,Unity WebGL 是 APP 手游性能的 1/3,开发者应该特别注意 CPU 侧的性能瓶颈。

可通过 Benchmarking Unity performance in WebGL 了解 Unity 不同模块与手游 APP 的性能差异。

  • GPU 性能差异

Unity 是以 WebGL API 进行渲染,其中 WebGL1.0 相当于 OpenGLES2.0, WebGL2.0 相当于 OpenGLES3.0。

WebGL 在原生的渲染API进行封装存在少量负荷带来的开销,但基本的渲染能力与原生 APP 接近。

渲染特性如 GPU Instantcing、SRP Batcher 需要 WebGL2.0。 (需要注意的是,当 APP 手游使用了这些特性时,在小游戏未开启 WebGL2.0 时则会进一步拉大差距)

WASM VS JS 的运行差异 ​

WASM 是强类型语言,这将使得 JIT 优化能更准确预判运行期类型,因此相对于 JS 能更快达到 JIT 指令优化后的峰值。通常而言,WASM~=1.5 * JS, 即 JS 运行效率的 150% 以上。

Unity 引擎目前没有很好地针对浏览器环境优化(比如 WASM 与宿主接口互调频次、不必要的代码路径裁)会比较臃肿,一些应用场景反而不如 JS 轻量。

因此,两者在实际使用时并不能简单以语言算力对比,需要以实测游戏为准。

系统平台之间的性能差异

Android 与 Windows PC 使用 V8 作为 WASM 虚拟机内核,支持 JIT,在相同算力条件下两者性能是接近的。但要注意移动平台散热更差,因此对性能更苛刻。

iOS 默认为普通模式,不支持 JIT,可用于超休闲游戏;中重度游戏建议开启 iOS 高性能模式以支持 JIT,但该模式需要更多精力进行调优,特别是启动发烫与内存方面。

二、优化目标 ​

由于 Unity WebGL 的性能无法完全达到原生 APP 的性能水平,开发者需要根据不同品类的游戏建立不同的最低机型要求和流畅度标准。 建议:

轻度休闲游戏应保证低档机型 30fps 以上,需特别注意机型兼容性(可使用小游戏云测获取兼容性报告),以达到买量用户覆盖度。

中重度游戏应保证中高档机不限帧时达到 40fps 以上,实际运行可限帧 30 以保持长时间挂机运行的发热量。

详细的基准机型与性能要求可参考性能评估标准,平台对上线无严格的性能要求,需要开发者根据自身游戏商业化要求制定。

三、优化工具 ​

3.1 Unity Profiler ​

Unity Profiler 的运行原理是在 Unity Editor 监听固定端口,Unity WebGL 游戏运行时以 WebSocket 连接并定期发送性能数据。

  • 工具需要开启 development 模式,对性能有较大影响

  • 可获取函数热点、内存与模块上报数据(比如物理、动画等)

  • 不是很稳定,部分版本会出现无法连接的情况

  • 内存数据不准确,并不能反应真实使用情况,内存工具请查阅优化 Unity WebGL 的内存

四、优化手段 ​

  • 配置加载与协议解析

不用使用 XML、JSON 解析大文件,尤其是在游戏启动阶段,字符串类型解析器将耗费大量 CPU 算力与产生 GC。比如大型游戏在使用 Addressable 时 catalog 文件往往会超过 10MB,导致解析过慢而影响启动速度,此时应使用其他资源管理比如 AssetBundle 来减少资源索引文件大小。同样地,在游戏过程中也尽量避免这类 CPU 消耗。

  • Lua 性能

Unity WebGL 环境的 Lua 不支持 JIT,因此需要避免用于重度逻辑。可使用 Android CPU Profiler 性能调优查看 Lua 的耗时占比。

  • 物理性能

请参考文档优化物理性能,适当调整 Fixed Timestep 与 Maximum Allowed Timestep 降低计算频率。

  • 实例化

由于 Unity WebGL 是单线程模型,因此耗时长的 CPU 运算会影响帧率。较为普遍的是 AssetBundle 加载与 Prefab 实例化,通过优化逻辑分帧加载可大幅度提升游戏体验。

  • 限制帧率

限制帧率有利于降低设备发热量与提升游戏时长,对帧率不敏感游戏建议使用, 可使用 Application.targetFramerate 限帧,当帧率为 15/30/60 使用 raf 分片处理,其余值使用 timer 控制。

  • 限制分辨率

限制分辨率以一定的画质牺牲来降低对设备消耗,在小游戏平台请勿使用 Unity 的 SetResulution 等接口修改分辨率,应使用 DevicePixelRatio 来控制(仅支持 iOS、Android)。

  • 使用压缩纹理

在压缩纹理不支持的情况下,纹理会由于需要在 CPU 中软解为 RGB/RGBA32 造成巨大的 CPU 和内存消耗,运行中的这种行为会造成明显的帧率卡顿问题,建议使用压缩纹理优化。

  • WebGL2.0说明

请查阅 WebGL2.0 渲染支持说明

  • 减少Drawcall

大量 DC 会造成非常大的 CPU 压力,当场景渲染物件过多时应该采取适当的措施减少 Drawcall

标准渲染管线,适当使用 Static Batch 以减少 DC 可开启 WebGL2.0 时使用 GPU Instantcing 尽可能地设置 LOD、可见范围以降低渲染物件

  • 使用SRP Batcher Uinty WebGL 的 SRP Batcher 需要两个先决条件:Unity 2021 以上 + WebGL2.0