查看原文
其他

Cocos 性能优化的 N 种策略:降低 DrawCall 与面数、强制调用独显……

youyou COCOS 2023-03-16

iles 优化后,游戏实录


前段时间,我们发布了 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 渲染流程:

  1. 把整个场景按区域划分,每个区域的范围是 5*5*5。

  2. 场景加载的时候将草按区域添加进对应的 InstancedBuffer 中(不会生成实际的草节点),这些 InstancedBuffer 填充完后运行时不会再进行修改。

  3. 场景运行中只需要对区域进行视锥体剔除,而且没有运行时填充 InstancedBuffer 的消耗,整个效率会高很多。

  4. 测试了草地的优化后海底遍布的物体也使用了同样的方式来优化。



所有这些优化加起来后性能有了显著的提升,最大的场景为优化前有 600w 面,优化完后基本可以控制在 50w 面以内。


渲染 Pipeline



我们增加了一些 pipeline 条件控制节点,尽量避免不必要的渲染流程,渲染整个屏幕还是很耗性能的。


优化开始场景



开始场景里,摄像机的视角是固定的,摄像机只会看到岛的前半部分,后半部分是看不到的,在生成海底物体的时候可以增加一下判断,处于岛的后半部分的物体不用生成,这样可以减少运行时的开销。


渲染分辨率


屏幕的渲染分辨率对于 GPU 计算的消耗影响是很大的。我们发现有些用户的机器设备并不是很好,但是有可能连接了一个很高分辨率的机器,基于不同的渲染质量,我们控制了他最大的渲染分辨率。

let resolution = [1120630]
if (renderSetting.realQuality === RenderQulity.High) {   
    resolution = [1960960]
}
else if (renderSetting.realQuality === RenderQulity.Medium) {
    resolution = [1334750]
}


提升开发效率



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


往期精彩

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存