游戏性能优化-cocos creator

1,789 阅读5分钟

吭哧吭哧开发完一款游戏,性能优化必不可少。

根据查到的大佬们的教程和自己的一些实践做一个总结记录,方便以后对照查看。

参考链接

Cocos Creator 性能优化:DrawCall

CocosCreator客户端优化系列(二):渲染优化

性能优化一般分为四个方面:

  1. 加载优化(进游戏前加载)
  2. 渲染优化(加载完后渲染到屏幕)
  3. 内存优化(玩游戏过程会不会卡)
  4. CPU占用优化(玩游戏过程会不会卡,是不是非常烫)

1.加载优化

加载的优化就是为了缩短进游戏的时间,那只要加载的文件小了,速度就会快了。

资源压缩
  1. 图片压缩。利用工具,比如pngquant,yasuotu等。(背景图应该使用jpg,因为同等情况下,jpg比png小)
  2. 音效压缩。对音乐音效压缩(声道、采样率等),mp3格式占用小
  3. 字库压缩。应该尽可能的少用字库,换成位图字体,使用的话也要进行压缩。
合图

把资源模块化打成图集,注意大图不要打进去,并且要合理利用2的幂次方空间,最大不要超过2048*2048,否则会出现黑屏。

九宫格拉伸

纯色方形图使用九宫格拉伸,假设是带圆角的按钮资源,可以将中间部分使用九宫格拉伸。

拆分预制体

大的预制体根据情况拆分成小的,遵循单一职责。加载10个100k的和加载1个1M的时间,往往是10个100k的更快。另外应该把不是首次需要用到的prefab异步加载 或者 使用延迟加载策略等

分帧加载

例如一次性需要实例化很多个预制体时,通过settimeout等方法分帧加载

切割引擎模块

根据项目情况,切割引擎不必要的模块

静态资源放到resources之外

不需要动态加载的资源放到resources文件夹之外,动态加载的文件需要建立映射,增大setting文件。

压缩混淆

使用uglify压缩等

组件化开发

尽量使用组件化开发,减少重复代码

2.渲染优化

DrawCall

渲染优化主要集中在优化DrawCall数量上,也就是常说的DC。draw call翻译过来(瞎翻译)是绘画调用。

DrawCall是CPU调用图形编程接口,命令GPU进行渲染的操作。CPU每次调用前需要对数据加载读、写、处理,改变渲染状态等操作,会消耗一定的性能和时间。通常GPU处理数据是非常快的,硬件的并行能力使其一次绘制1个图形或者是1000个图形速度上相差无几。

所以如果CPU需要处理的数据尽量少,处理的次数尽量少就能达到优化目的。

上面说的不明了,举个例子:假设界面上需要绘制两个正方形,它们有重叠部分,那么要做的有两件事

  1. 被遮挡的部分不需要画,也就是要处理的数据少了--这部分引擎渲染管线已经处理好了
  2. 每次尽量多画,理论上绘制两个图形需要提交两次数据,如果我们能把数据合并成一批处理,drawcall的次数也就少了。

怎么合批至关重要,下面列出一些方法:

  1. 合图。将散图打成一张大图,一般建议将同一个界面所需的图片打成一张(这不仅有利于减少drawcall,也方便内存管理)。在使用同一张合图的时候,只要保持相邻并且渲染状态相同,就不会打断合批。

合图的方式有引擎的自动图集Auto Atlas、使用软件TexturePacker(写个脚本自动使用软件打包)、引擎的动态合图Dynamic Atlas

  1. 位图字体。使用系统字体和动态字体(如TTF格式)的字体会打断合批(label绘制在纹理中),如果使用位图字体将文字打成位图,甚至可以将位图也打到上面的合图中,麻麻再也不用担心无法合批了。引擎还提供了针对系统字体和动态字体的优化,根据情况开启CacheMode,也可达到合批效果👍👍👍。
  2. 节点快照。如果界面UI基本不变的情况下,还可以使用节点快照缓存,可以大大降低drawcall。
  3. 节点相邻。很多情况下我们可以手动调节节点顺序,让纹理相同,渲染状态相同的节点相邻,合批就不会被打断。

打断合批的情况有哪些呢?改变纹理状态(预乘、循环模式和过滤模式)、改变 Material(材质)、改变 Blend(混合模式)、自定义shader、使用mask、插入spine等等

节点隐藏

设置节点的active,会重新渲染节点数,如果节点频繁使用,但数量不多,可以把节点设置到看不见的位置,下次要使用把位置调回来就行。

3.内存优化

内存生命周期分为3步,

  1. 分配你所需要的内存
  2. 使用分配到的内存(读、写)
  3. 不需要时将其释放\归还 想要优化就得管理到位,该释放时就释放。
设置自动释放

在有多个场景时可通过,可通过勾选引擎的“自动释放”功能,在切换场景时自动释放静态资源

资源管理

动态资源可以手动管理释放,例如写个资源引用计数脚本,配合getDependsRecursively获取依赖,准确释放计数为0的资源

对象池

使用对象次管理重复使用的节点,减少alloc和GC的开销

4.CPU占用优化

  1. 慎用全局变量,访问全局变量需要遍历作用域
  2. 尽量减少节点数量
  3. 场景少挂prefab,尽量动态加载
  4. 分离逻辑帧和渲染帧
  5. 注意使用闭包
  6. 少用滤镜、遮罩
  7. 简单的碰撞无需需要碰撞系统,可以考虑AABB包围盒,位置重合等
  8. ... -----待更新