Cocos 性能优化的 N 种策略:降低 DrawCall 与面数、强制调用独显……
前段时间,我们发布了 3D 跑酷闯关+建造游戏源码 iles,开源的同时也上线了 Steam。我们希望借助这一案例,让开发者看到更多引擎所构建的场景的细节,同时,作为引擎研发者,我们也能亲身体验一下 Cocos Creator 开发游戏的全流程,以此发现引擎的不足与痛点,为之后的迭代提供参考。
游戏发布后,许多开发者和玩家将自己的体验感受与建议告诉了我们。参考大家的反馈,我们在 iles 的性能优化方面做了更多探索,本文将分享一些优化思路与优化手段,供有需要的小伙伴参考。
强制使用独立显卡
很多 windows 机器都会拥有两张以上的显卡,在某些情况下机器会自动选择性能比较低的集成显卡来降低性能。在游戏应用里面,我们可能希望程序一直都运行独立显卡来保证游戏的流畅度。
iles 基于 electron 发布,在此基础上我们查找了一些解决方案:
环境变量里设置 SHIM_MCCOMPAT=0x800000001 [1]。以下是 iles 启动的 start.cmd 文件:
set SHIM_MCCOMPAT=0x800000001
cd %~dp0
start ..\..\iles.exe
添加 electron 启动参数 [2]:
app.commandLine.appendSwitch('force_high_performance_gpu')
查了下 chromium 支持的版本在 101.0.4923.0 [3],electron 对应版本在 19.0.0 之后 [4]。
为了检测启动后机器的显卡信息、及其是否正确使用了独立显卡,我们写了一个测试程序,提供给大家参考:
GitHub - 2youyou2/electron-detect-gpu:
https://github.com/2youyou2/electron-detect-gpu
优化 DrawCall 以及面数
> 海面
整个海平面是一个很大的区域,为了保证海浪运动得比较自然,需要的顶点数就比较多,但是我们又不希望整个海平面都使用非常多的顶点数,理论上我们只需要近处的细节比较多,远处的细节可以少一点。
基于这个思考,我们将海平面分为9个区域,只有中间的部分保持高顶点数,周围使用少一些顶点数的模型,但是为了保证区域间的顶点动画是完美衔接的,高模和低模的边缘顶点数也是需要完美匹配的。
下面是我用 blender 操作的流程:
添加一个 Grid 类型的 Mesh。
切换模式到面编辑模式,选中边缘以外的面,右键选择 un-subdivide。
可以看到优化完后顶点会少很多。
> 树
iles 中遍布了大量的树,原始的树的模型面数还是挺高的,一棵树有300面左右。
上图这个关卡有近2000棵树,差不多 60w 面。我们添加了 lod 的支持,在近处使用比较精细的 lod,在远处使用粗糙一些的低模,在一定距离外剔除掉这个模型的渲染。
在 blender 里面做一个粗糙的低模还是比较简单的:选中模型添加一个 Decimate 类型的 Modifier,调节 ratio 减面到一个能接受的程度。
接着写了一个比较简易的 lod 选择器,在摄像机10米以内的话使用 lod0,在1000米以内使用 lod1,再远一点的就会剔除掉。在创意工坊编辑模式下希望看到的距离更远一些,所以设置在3000米以内还能看到树。
> 草
游戏中草的数量是非常多的,地块面积越大,草的数量就越多,像下面这个大场景里面草的数量很轻易就上万了。
如果我们按照普通模型的方式去渲染草地的话,每一个遍历都会消耗大量的性能。场景裁剪、instance 填充,这些是性能消耗的重灾区。
这里我希望完全自己控制整个草地的 instance 渲染流程:
把整个场景按区域划分,每个区域的范围是 5*5*5。
场景加载的时候将草按区域添加进对应的 InstancedBuffer 中(不会生成实际的草节点),这些 InstancedBuffer 填充完后运行时不会再进行修改。
场景运行中只需要对区域进行视锥体剔除,而且没有运行时填充 InstancedBuffer 的消耗,整个效率会高很多。
测试了草地的优化后海底遍布的物体也使用了同样的方式来优化。
所有这些优化加起来后性能有了显著的提升,最大的场景为优化前有 600w 面,优化完后基本可以控制在 50w 面以内。
渲染 Pipeline
我们增加了一些 pipeline 条件控制节点,尽量避免不必要的渲染流程,渲染整个屏幕还是很耗性能的。
优化开始场景
开始场景里,摄像机的视角是固定的,摄像机只会看到岛的前半部分,后半部分是看不到的,在生成海底物体的时候可以增加一下判断,处于岛的后半部分的物体不用生成,这样可以减少运行时的开销。
渲染分辨率
屏幕的渲染分辨率对于 GPU 计算的消耗影响是很大的。我们发现有些用户的机器设备并不是很好,但是有可能连接了一个很高分辨率的机器,基于不同的渲染质量,我们控制了他最大的渲染分辨率。
let resolution = [1120, 630]
if (renderSetting.realQuality === RenderQulity.High) {
resolution = [1960, 960]
}
else if (renderSetting.realQuality === RenderQulity.Medium) {
resolution = [1334, 750]
}
提升开发效率
Cocos Creator 3.6.0 新增编辑器预览模式,我们可以在编辑器中运行和调试游戏,对于提升开发效率很有帮助。iles 升级到了 v3.6.1,整个体验还是很不错的。
提升游戏体验
除了优化性能,我们还增加了一些游戏内容或模块,提升玩家的游戏体验。
1. 新增排行榜,使用 leancloud 免费版,每天有一万次 api 接口调用次数。
2. 添加了辣椒道具,搭配火焰特效,吃了能够加速奔跑。
3. 添加了弹力蘑菇,能将小鸡弹上天空。
4. 添加了漂浮木箱,模拟水面浮力,增加趣味性。
5. 支持了键盘和手柄控制。
6. 优化加载过程,添加加载界面。
>> 左右滑动查看更多
资源下载
目前 Cocos Store 上的源码为优化前、基于 v3.6.0 构建的源码,优化后、升级到 v3.6.1 的源码将在整理后上传,敬请关注!
点击文末【阅读原文】下载源码
https://store.cocos.com/app/detail/4010
iles 下载体验 - Steam
https://store.steampowered.com/app/2001150/iles/
参考链接
[1] 环境变量设置
https://steamcommunity.com/groups/SteamClientBeta/discussions/0/154644787621730542/
[2] Electron 文档
https://www.electronjs.org/zh/docs/latest/api/command-line-switches#--force_high_performance_gpu
[3] chromium 101.0.4923.0
https://github.com/chromium/chromium/releases/tag/101.0.4923.0
https://github.com/chromium/chromium/commit/f35df3e3e2276c4ec658d66961789ceb4fc4e278
[4] Electron 版本下载
https://www.electronjs.org/releases/stable?version=19&page=4
往期精彩