9月份 Cocos 技术开发分享会第 2 期在深圳圆满举行,近期我们将对活动干货进行整理,陆续在公众号上发布,没能去到深圳现场的开发者可以关注一下!对于分享的议题有哪些疑惑也欢迎在文末给我们留言!

本文基于 Cocos Creator v2.1.2

《Cocos Creator ScrollView 性能优化》

讲师:Cocos 技术顾问组

分享原因:

Cocos Creator 的 ScrollView 组件是游戏开发中常用的组件,在一些商城界面、排行榜界面、任务列表、背包系统等模块中经常会使用到它,但同时它的开销也非常大。当我们需要显示的条目比较多时,单纯简单地去使用的话,往往性能不大理想。

Cocos Creator 只实现了最基本的 ScrollView,相应的优化还需要我们根据项目的情况来进行针对性的优化。

常见问题:

当数据量比较大时,我们很容易碰到两个问题:

  • DrawCall 的数量比较高,渲染性能比较低

  • 整个 Scrollview 的节点数太多,导致隐藏或显示界面时的 onEnable 和 Disable 开销比较大

比如下面这个界面:

Demo 中的 ScrollView 1 场景

ScrollView 当中有 20 个 Cell,总共的 DrawCall 达到了 790,单个 Cell 大概有 50 个节点,总共就有差不多 1000 个节点,这时我们的开销会变得非常的大

常规优化方式推荐:

1、合并渲染批次,降低 DrawCall,提升渲染性能

有两个方法可以使用:

(1)使用自动图集或使用 TexturePacker 对碎图进行打包处理:

这样操作的话,可以让多个 Sprite 渲染的纹理都是同一张图集图片,合并这些 sprite 的渲染批次,就可以减少 DrawCall 以及 CPU 的运算开销。

这里我使用了 AutoAtlas 来实现,关于 AutoAtlas 的使用可以[参考文档],让我们来看下效果:

同样是 20 个 Cell,DrawCall 降低到了 556,相比较之前有了比较明显的降低。

优化到这个程度还不够,如果你是在 Google 的 Chrome 浏览器上进行调试的话,推荐你使用 spector.js 这个插件,通过这个插件你可以看到每个 DrawCall 对于纹理的处理情况。对于原生开发,则可以使用 XCode 中的 GPU analysis功能。

(2)开启 dynamicAtlas 功能

开启这个功能,在 main.js 中的 window.boot() 方法内加入下面的两行代码即可:

cc.macro.CLEANUP_IMAGE_CACHE = false;
cc.dynamicAtlasManager.enabled = true;

开启之后,我们可以看到 DrawCall 大幅下降,部分 DrawCall 已经合并。

2、对于 Label 的处理。

Label 的处理跟前面的优化方案选择有关系:

(1)如果使用了自动图集或 TexturePacker 对碎图进行合并的话,可以选择 Label 使用 bmfont 字体,而不是使用系统字体,同时将 bmfont 使用到的纹理资也一起合并到图集资源中。

可以看到,DrawCall 又进一步地降低了,目前运行的效果是 330 个 DrawCall。

(2)如果前面使用的是 dynamicAtlas 的功能,那么可以选择 Label 使用系统字体,同时将 Label 的 CacheMode 属性更改为 BITMAP。

这个模式下会将 Label 的纹理当作一个 Sprite 纹理,并且参与到 dynamicAtlas 中去,这样就可以跟 Sprite 的纹理进行合批处理。

从这两个方案可以看出来,优化策略都是想办法对 DrawCall 进行合并批处理,只是使用 dynamicAtlas 更加地智能,同时也可以更好地适应复杂的节点结构。

但需要注意的是,dynamicAtlas 会有额外的 CPU 计算以及动态纹理的绘制开销,因此需要根据项目的情况去选择使用。

3、通过 Cell 的位置进行计算,让显示范围外节点的 opacity 为0,即不显示,减少  DrawCall 。

在可视范围外的节点,本身我们就不可见,所以就不需要它再进行绘制,平白增加 Drawcall。我们可以将这些可视范围外节点的 opacity 属性设置为 0,从而避免绘制,可以有效的降低 DrawCall。

update (dt) {var viewRect = cc.rect(- this.view.width / 2, - this.content.y - this.view.height, this.view.width, this.view.height);for (let i = 0; i < this.content.children.length; i++) {const node = this.content.children[i];if (viewRect.intersects(node.getBoundingBox())) {node.opacity = 255;}else {node.opacity = 0;}}}

这里我将判断逻辑放在了 Update 函数中,你也可以将这段方法放到 ScrollView 的滑动回调中去,这样的话不用每帧都计算,只在需要的时候才会去进行计算,节约一些 CPU 的开销。

最终效果可以看到,在启用 dynamicAtlas 的方案上,DrawCall 可以降低到 68,相比较最原始的 790 个 DrawCall,效果显著。

4、资源处理,减少 Mask 组件数量

通过对资源的处理,减少 Cell 中使用 Mask 组件的数量,尽量不使用 Mask 组件。

由于 Mask 组件需要在 stencil 和 content 前后都添加修改 gl 状态的 render command,因此使用 Mask 会打断我们的 DrawCall 批处理。

对于一些特殊的显示,例如圆角的 icon 等,如果条件允许,尽量不要使用 Mask 组件来进行处理,而是通过对资源进行处理达到同样的效果。

目前 Mask 组件、Spine 组件、DragonBone 组件都会打断批处理,在节点结构上我们要避免被打断的情况发生。

在这个 demo 当中,每一个 icon 都有一个使用了 Mask 组件的子节点,我们去除它,效果如下:

最终就只有 18 个 DrawCall,基本上是极限地 DrawCall 优化了。毕竟 ScrollView 本身就有一个 Mask 组件,这个组件我们无法避免,必须要使用。

5、复用 Cell 节点,减少节点数

对 Cell节点进行复用,减少节点数,这一块改动比较大。前面都是对 DrawCall 的优化,但实际的节点数量还是很多。当显示或隐藏这个界面时,大量的节点会带来大量的 enable 和 disable 的开销。

因此我们通过复用节点,根据滑动情况实时更新 Cell 位置以及显示内容的方式,减少节点的数量。具体操作可以参考[Cocos Creator 官方示例]中的 ListView 示例。

原理如下:

具体代码可以参考 demo 工程中的 ScrollView 3 场景的实现,最终效果如下:

20 个 Cell 的 ScrollView,实际上只是 7 个 Cell 节点在不停的复用显示,从而表现出来的。与之前的效果以及 DrawCall 相同,但实际使用的节点数大大降低,大约有 300 个节点,相比较之前的 1000 个节点大幅降低。

6、分帧加载节点与节点快照

由于背包模块的需求,往往首次需要同步加载并显示多个 Cell 节点,所以往往会造成加载卡顿、加载崩溃等问题,针对这个问题,我们提出了分帧加载节点与 renderTexture 节点快照组合而成的优化方案。

分帧加载方案,主要利用的是 ES6 特性中的异步加载方案:Generator(协程)。下面是节选自本次分享会 PPT 中的对协程执行流程的讲解:

协程能够有效地暂停当前语句并将转移它的执行权,等待执行权返回。这个过程可以一直重复,直到语句执行完毕。分帧加载方案就是利用协程的这一点特性,在每次语句循环执行时,将加载代码的执行权转移给下一帧去执行,从而达到分帧加载的效果。

节点快照方案的原理是:首先放置一个 Cell 参考节点,放置在可渲染但是不可见的区域(可通过多摄像机实现)。之后每当需要新增一个 Cell 节点,都让 Cell 参考节点去做相应变换,变换结束后利用 Camera 和 RenderTexture 将渲染结果[截图]下来,再交由 Content 中新增的 简易 Cell 节点渲染出来即可。

未优化前,500 个 Cell 节点 DrawCall 达到 2514 个,总节点数达到节点总数 3048 个。

优化后的效果如下:

优化完之后,加载完成时 DrawCall 稳定为 18 个,节点总数 548 个,效果显著。

以上就是一些常用的 ScrollView 性能优化手段,欢迎大家在 Cocos 论坛上一起讨论更有价值的游戏优化方案。

参考文档

查看截图方案

https://docs.cocos.com/creator/manual/zh/render/camera.html#%E6%88%AA%E5%9B%BE

Auto-atlas Asset:

https://docs.cocos2d-x.org/creator/2.1/manual/en/asset-workflow/auto-atlas.html

UI 渲染批次合并指南:

https://docs.cocos.com/creator/manual/zh/advanced-topics/ui-auto-batch.html

背包模块优化方案地址:

https://github.com/Jno1995/ScrollViewTest

演讲视频

搭配 PPT 观看更棒哦,在公众号内输入【性能优化】可获取演讲 PPT。

极限开发《TheCode》和《Shoot the F》创作笔记

Cocos Creator 2.1.3 正式发布

Cocos 荣耀讲师征集计划

微信创意小游戏橙皮书发布

用 Cocos Creator 制作平台跳跃游戏

Cocos技术派|3D小游戏《快上车》技术分享

Cocos海外开发者专访:遗憾的是没早点开始做游戏

我的小游戏开发之路|腾讯TGideas周桂华(花叔)

Gameloft 如何打造 Facebook 小游戏玩转越南市场

Cocos Creator 零基础入门教程 | 免费

Cocos 引擎 UI 全新升级:进一步提升编辑器体验

我就知道你“在看”▼

Cocos Creator ScrollView 性能优化相关推荐

  1. Cocos Creator性能优化-2-包体优化

    对于Cocos Creator包体优化可分为 1.项目设置 1.模块设置 通过去除无需使用的模块来减少包体 (微信小游戏还支持引擎插件可在打包时勾选) 2.resources 总而言之不需要动态加载的 ...

  2. Cocos Creator—定制H5游戏首页loading界面

    Cocos Creator从1.0版本发布到现在也有一年多了,按理说一些常见的问题网上都有解决方案,例如"如何自定义首页加载进度条界面"这种普遍需求,应该所有人都会遇到的,因此也有 ...

  3. Cocos Creator 性能优化:DrawCall

    Cocos Creator 性能优化:DrawCall(全面!) title: Cocos Creator 性能优化:DrawCall 前言 在游戏开发中,DrawCall 作为一个非常重要的性能指标 ...

  4. Cocos Creator性能优化---DrawCall

    前言 在游戏开发中,DrawCall 作为一个非常重要的性能指标,直接影响游戏的整体性能表现. 无论是 Cocos Creator.Unity.Unreal 还是其他游戏引擎,只要说到游戏性能优化,D ...

  5. Cocos Creator 性能调优优化集锦

    01 为什么要做性能优化? 性能:是一种优秀的能力.唤醒快.运行持久.稳定. 这种能力在游戏上能让你的用户感觉很爽,表征表现为加载快.手机不发热.运行流畅.不卡顿. 所以,性能优化的终极目标是让你的用 ...

  6. Cocos Creator 性能优化——对象池

    ​对于游戏开发人员来说,性能优化是一个永远绕不过的话题,极致的性能是我们毕生的追求,今天就来带大家学习一下性能优化方法之一--「对象池」. 为什么要使用对象池? 在开始之前要先弄明白为什么要使用对象池 ...

  7. Cocos Creator 基于 Spine 动画的 AVATAR 换装系统优化

    很多游戏开发团队都正在使用 Spine 动画软件来制作人物 AVATAR 动画.今天,玩吧技术专家组的红孩儿将以玩吧 APP 中的游戏<噜噜喵>为例,同大家分享基于 Spine 动画的 A ...

  8. cocos微信小游戏开发-http请求-使用微信云函数-toast-loading-动态加载图片-添加触摸事件-微信分享-label点击事件-背景音乐音效-程序活动状态判断-性能优化

    cocos开发微信小游戏相关-<益智推箱> 扫码查看功能,有需要可直接提问 Cocos Creator 3.4 用户手册 cocos creator基本操作 微信开发文档|云函数 1. h ...

  9. Cocos Creator 性能调优:如何减少 2D/3D DrawCall?

    Cocos 中文社区第4期有奖征稿活动火热进行中,iWatch SE.坚果投影仪等丰厚奖品等你来拿,点击文末[阅读原文]进入社区专贴,把你的聪明才智向我们砸来吧! 点击查看活动详情 本文即为此次社区征 ...

最新文章

  1. 一线大厂BAT资深移动开发者倾情打造,教你从0构建App
  2. bash: /usr/lib/jvm/jdk1.7.0_80/bin/java: No such file or directory 问题
  3. html漂浮广告随页面移动代码,JS漂浮广告代码,慢慢漂移的广告JS代码
  4. python 原始数据输出函数 repr
  5. android 二级列表拖动排序_Excel的数据透视表六种排序方法
  6. arcgis-online-python-scripts
  7. java进阶 2018_Java Web基础入门2018版
  8. MySQL学习笔记_10_MySQL高级操作(下)
  9. 【BZOJ3437】小P的牧场,斜率优化DP
  10. [翻译]XNA在线俱乐部网站即将开站!
  11. mysql的财务视图_Mysql中的视图
  12. 疫情之下,计算机仿真程序告诉你,没事别乱出门!企业复工务必做到八个“一”...
  13. rsync的作为版本库的用法(自带时间后缀)
  14. 多用户商城系统三级分销的设计和实现
  15. Ubuntu18.04设置系统默认音频设备:使用pavucontrol命令
  16. 解决问题—麦肯锡方法:解决问题的七个步骤
  17. 技术前沿与经典文章20:历史上54位伟大物理学家、科学家的专属LOGO(六)
  18. 微信开发笔记:生成带参数的公众号二维码
  19. AtCoder Regular Contest 115 C - ℕ Coloring
  20. ada:世界上第一位程序员

热门文章

  1. Myeclipse配置tomcat服务器
  2. [翻译] 使用FXGL创建一个简单游戏 Pong (FXGL 11)
  3. 各大平台卡卷直充接口源码
  4. Flink+Iceberg环境搭建及生产问题处理
  5. 无人驾驶感知篇之融合(二)
  6. 基于单片机智能窗帘控制系统设计-protues毕设课设
  7. luogu P2561 [AHOI2002]黑白瓷砖(polya定理)
  8. 50幅精美绝伦的世界各地风光摄影作品欣赏(上篇)
  9. java 给qq邮箱发邮件_Java使用QQ邮箱给其他邮箱发邮件
  10. 程序输出urf-8编码的xml文件中文(汉字)乱码问题解决方法