LazyAn-—CocosCreator优化系列(一):加载优化

LazyAn-—CocosCreator优化系列(一):加载优化_第1张图片

ps:本系列转载自大佬-BigBear023,为了方便日后学习,查阅和分享,现对系列文章重新进行整理、排版并对部分内容进行修改;如有不妥,请大佬联系我删除。原文链接:

https://blog.csdn.net/zzx023/article/details/85318028

本系列分为四个部分:加载优化、渲染优化、内存优化、CPU占用以及性能优化。

这些措施每一个都会带来多方面的优化效果,但也有部分措施拥有一定的局限性,因此需要各位理解后根据项目实际情况选择使用。

  • 图片资源的处理

项目中避免大尺寸的图片出现。像下面这样的图片:

LazyAn-—CocosCreator优化系列(一):加载优化_第2张图片

其实我们的项目当中经常会出现这样的资源,其实这样的图源完全可以通过九宫格的方式进行拉伸得到,因此我们的资源其实只需要像下面这张图一样就行

LazyAn-—CocosCreator优化系列(一):加载优化_第3张图片

这样一个方面图片的大小变小了,我们在进行加载时自然速度将会加快。另一方面也会带来内存的减少以及包体的减少。另外有一点也要格外注意,cocos creator所支持的最大图片尺寸为2048*2048,超过这个尺寸的图片在显示时会有问题,常见于一些Spine动画打包出来后没注意资源图片尺寸,导致动画显示异常。

如果是地图资源超过2048*2048,常见于一些mmo项目,这种情况下,需要对地图资源进行切分,切分成小于2048*2048的若干图片,在游戏中再拼接在一起。当然这样拼接的话在摄像机或者地图移动时可能会有白边出现,需要特殊处理,这里就不详细说了。

LazyAn-—CocosCreator优化系列(一):加载优化_第4张图片

另外,类似这样的图片资源也是需要避免的,虽然每个数字的颜色都不一致,但其实都可以通过程序改变color的方法去达到,只需要使用时美术告知字号即可,没必要每一个颜色就出一张图,导致每次显示不同颜色字体时,还需要进行额外的加载。同时也带来内存和包体的提升。

  • 图片资源的模块化

LazyAn-—CocosCreator优化系列(一):加载优化_第5张图片

类似这样,将各个界面的美术资源、帧动画分类并且打包成图集也是比较好的处理方法,将资源进行模块化。这样在加载时,以及游戏运行时,会有以下几点好处:

    1.提升加载速度

       省去了多次打开/关闭文件所带来的时间损耗

    2.减少文件的体积

       多张图片合并到一起,在包体上面会有一定的优化

    3.减少DrawCall

       使用时,由于这些美术资源都是一起配合使用的,因此放在一张图集           中,可以减少渲染的DrawCall数量,对渲染的性能也有优化的作用

同时在不需要使用这些资源时,比如说某个界面 不需要再显示时,可以将这个界面的资源统一释放,避免占用内存。另外通用资源可以统一打包在一张图集中,让这些通用的常用资源常驻与内存,方便使用。避免频繁的重复释放和加载。另外关于图集的使用,在creator 2.x以上版本,支持TexturePacker的多边形图集。

也就是支持图集输出时,TrimMode为Polygon,这个模式的像素填充率将会更高,打包出来的图集尺寸将会更小一些。不过这个模式需要付费版的texturePacker才能使用。

  • 图片、纹理压缩

  • 图片压缩

首先是图片资源的压缩处理,这一块和程序代码无关,对加载速度影响也不大,但是可以带来包体上具体的提升,因此也放在这里说一说。例如下面的图片,原图的大小是1M左右,我们通过选择合适的pixelformat以及合适的抖动算法(有仿色),可以将图片压缩到198kb,整体图片体积压缩了80%,同时画质上面的损耗并不明显,可以接受。

LazyAn-—CocosCreator优化系列(一):加载优化_第6张图片

在这里要说明一下PNG图片的rgba颜色对于图片效果的影响:

LazyAn-—CocosCreator优化系列(一):加载优化_第7张图片

比如RGBA8888这种pixelformat,它意味着rgba每一位占用8个bit,这样每个像素占用4个字节,因此这个压缩模式对于图片可以最大限度的保真,但压缩比方面不大。

这里要注意的是,这个大小指的是图片占用的包体大小,也就是文件的大小,并不是图片在内存中的大小。关于内存的大小,需要注意的是,和文件的大小没有直接的关系。只和图片的长宽尺寸,也就是像素数量有关系。比如一张500k大小的1024*1024的图片,在内存中的占用大小为1024*1024*4 = 4M。同样一张进行图片压缩的500k大小的2048*2048的图片,在内存中的占用大小为2048*2048*4 = 16M。这一块要注意避免概念上的混淆。

当然也有一些我们可以很简单快速使用的一些压缩工具,在这里推荐给大家:一个是https://pngquant.org/  pngquant的命令行压缩图片,可以很好的集成到打包工具中。

LazyAn-—CocosCreator优化系列(一):加载优化_第8张图片

官方宣称是由73%的压缩,实际达不到,但压缩效果也是很好的了。

另外一个是TinyPNG,https://tinypng.com/一个在线压缩图片的网站,压缩比同样可观,同时对于图片的损耗很细微,基本看不出来。当然在线压缩对于图片的大小有一些限制,TinyPNG还提供了一个PS的插件,使用插件就可以在导出图片的时候随意进行压缩了

LazyAn-—CocosCreator优化系列(一):加载优化_第9张图片

  • 纹理压缩

 

1、PVR纹理压缩:

PVR纹理格式是针对iOS设备进行了特殊优化的一种纹理格式,这种纹理格式可以直接被PowerVR显卡所加载,因此在加载速度上可以带来巨大的提升。同时在内存方面也可以带来很大的优化。如果你的项目内存占用特别多,并且图片资源没有做过优化的,可以尝试使用压缩纹理。

但要注意的是压缩纹理是一定会带来图片上面的画质损失的,因此要根据实际的需求选择影响不大的素材进行使用。

常用的PVR压缩纹理的格式分为四种:PVRCT2 RGBA、PVRCT2 RGB、PVRCT4 RGBA、PVRCT4 RGB。区别在于带不带透明通道以及每个像素占用的大小。

PVRCT2,每个像素占用2bit。而PVRCT4,每个像素占用4bit。

例如一张2048*2048的图片,在内存中是16M

而如果我们使用了PVRCT2 RGBA模式进行压缩的话,他的内存大小为 2048*2048*2 / 8 = 1M

LazyAn-—CocosCreator优化系列(一):加载优化_第10张图片

如果你的图片想要最大限度的保真,同时使用PVR压缩纹理,那你可以使用PVRCT4 RGBA这种模式进行压缩。

如果你的图片是纯色的UI按钮图片,没有透明元素。可以尝试使用PVRCT2 RGB模式。

如果大家使用TexturePacker的话,可以在右下角很清楚快速的了解到这张图片在内存中的实际大小

LazyAn-—CocosCreator优化系列(一):加载优化_第11张图片

 2、ETC纹理压缩:

iOS使用的是PVR,而android使用的压缩纹理就是另一种了,那就是ETC

需要注意的是PVR只能在iOS上使用,而ETC的话,ETC1只能在android上使用。ETC2可以在目前的iOS上和android上同时使用,不过太低端的机子就不行了。

由于ETC1不支持透明通道,对于有透明度的图片,一般会使用ETC RGB + ETC Alpha的办法,输出成两张图,然后在程序中通过混合进行实现。

LazyAn-—CocosCreator优化系列(一):加载优化_第12张图片

例如上面这张图片,如果使用ETC的话,需要输出成下面的这样:

LazyAn-—CocosCreator优化系列(一):加载优化_第13张图片

Cocos Creator 可以直接在编辑器中设置纹理需要的压缩方式,然后在项目发布时自动对纹理进行压缩。针对 Web 平台,支持同时导出多种图片格式,引擎将根据不同的浏览器自动下载合适的格式。

Cocos Creator 支持导入多种格式的图片(具体见下表),但是在实际游戏运行中,我们不建议使用原始图片作为资源来加载。比如在手机平台上可能只需要原图 80% 或者更少的画质,又或者是没有使用到透明通道的 .png 可以将其转换成 .jpg,这样可以减少很大一部分图片的存储空间。

在 Cocos Creator v2.4 之前,配置压缩纹理只支持 Android, iOS, Web 和 微信小游戏 平台,而从 v2.4 开始,支持所有的小游戏平台。

LazyAn-—CocosCreator优化系列(一):加载优化_第14张图片

默认情况下 Cocos Creator 在构建的时候输出的是原始图片,如果在构建时需要对某一张图片进行压缩,可以在 资源管理器 中选中这张图片,然后在 属性管理器 中对图片的纹理格式进行编辑。

LazyAn-—CocosCreator优化系列(一):加载优化_第15张图片

Cocos Creator 在构建图片的时候,会查找当前图片是否进行了压缩纹理的配置,如果没有,则继续查找是否做了默认(Default)的配置,如果没有,则最后按原图输出。

如果查找到了压缩纹理的配置,那么会按照找到的配置对图片进行纹理压缩。在一个平台中可以指定多种纹理格式,每种纹理格式在构建时都会根据原图压缩生成一张指定格式的图片。

在运行时,这些生成的图片不会被全部加载,引擎会根据实际设备的支持情况,来选择加载合适格式的图片。cc.macro.SUPPORT_TEXTURE_FORMATS 列举了目前支持的所有图片格式,引擎加载图片时会从生成的图片中找到在这个列表中 优先级靠前(即排列靠前)的格式来加载。

用户可以通过修改 cc.macro.SUPPORT_TEXTURE_FORMATS 来自定义平台的图片资源支持情况以及加载顺序的优先级。

ETC1 和 PVR 格式都会用一个固定的空间来存储每个像素的颜色值。当需要存储 RGBA 4 个通道时,图片的显示质量可能会变得非常低。所以提供了一个 Separate Alpha 选项,该选项会将贴图的 Alpha 通道提取出来合并到贴图下方,然后整张贴图按照 RGB 3 个通道的格式来压缩。这样子每个通道的存储空间都得到了提升,贴图的质量也就提升了。

LazyAn-—CocosCreator优化系列(一):加载优化_第16张图片

官方文档:

https://docs.cocos.com/creator/manual/zh/asset-workflow/compress-texture.html

  • Prefab加载优化

Prefab这块的加载优化主要集中在两个地方:一个是load加载耗时优化,另一个是实例化耗时优化。首先先说一下prefab在使用时的步骤:

LazyAn-—CocosCreator优化系列(一):加载优化_第17张图片

了解了Prefab使用时做了哪些事情,我们也才好针对性的做优化。

来说一下常用的优化手段:

  • 合理拆分Prefab

越大的prefab文件在加载过程中的耗时是越长的,而且通常不是等比,而是以类似平方曲线这样的去增加时长的。例如读取一个100kb的文件,可能耗时也就10毫秒,但对于一个1M或者是2M的文件,我们在加载时就不是100毫秒,可能就是几百毫秒。

类似这样七八百kb的prefab文件,我们就要去思考一下,是不是里面的节点都必须做成一个prefab?是否可以拆分成2个以上的prefab,通过拼接的方式组合?

一个prefab我们可以将它看作为一个功能模块,而功能模块并不是越大越好,而是功能职责越单一越好,遵循这个原则,我们可以对prefab做更好的拆分。

  • 延迟加载资源

LazyAn-—CocosCreator优化系列(一):加载优化_第18张图片

在creator的资源管理器中点击编辑好的prefab资源,在属性检查器中我们可以看到延迟加载资源的选项。勾选这个选项可以减少prefab的加载耗时,但首次显示的耗时会增加。

这时由于勾选后,prefab所引用的资源,像图片、音效这些,不会在load时加载,而是会在prefab第一次显示的时候再进行资源的加载。

因此需要根据具体的使用环境进行选择。

  • 选择优化策略

LazyAn-—CocosCreator优化系列(一):加载优化_第19张图片

在prefab的属性检查器中,我们可以看到优化策略这个选项。这个也需要我们根据实际的使用情况进行选择。

当我们选择“优化多次创建性能”这个选项时,Prefab加载后会进行一个预处理的操作,这个预处理其实就是动态生成一些prefab的实例化代码,并把这些代码交给jit去进行优化。这样在实例化时的耗时将会大大减少,相应的,在load时的耗时会有所增加。

当我们选择“优化单次创建性能”这个选项时,prefab加载后会跳过预处理的步骤,这样在加载时的耗时会减少很多,但实例化时的耗时会增加。例如一些固定UI界面,由于方便加载场景或者进行功能划分,通常会做成prefab,这种prefab只会加载一次的,就可以选择这个选项,提升加载的性能。

需要注意的有一点:由于微信小游戏平台禁用了动态加载代码,类似eval这些不能使用,因此优化策略这个选项在微信小游戏平台是无效的。

  • 场景加载优化

场景加载的常用优化方案:

  • 合理使用预置体构成场景,分批异步进行加载

使用prefab来组成场景,这是最常用并且有效的手段。比如一些场景中的一些二级界面,没必要提前放置在场景中,可以通过动态加载的方式,等使用时再加载进来。

整个场景可以保留一些重要节点,比如背景图+主界面按钮。其他的一些资源都可以通过进入场景后再进行异步加载。可以有效的减少用户等待的时间,同时避免一次性加载一些不必要的资源进来。

  • 使用加载界面优化用户体验

通常对于一个复杂场景,加载需要一定耗时的,一定要通过一个加载界面去优化用户的体验,这个也是常用做法了。这里就不细说了

  • 使用延迟加载资源

LazyAn-—CocosCreator优化系列(一):加载优化_第20张图片

场景资源可以勾选延迟加载资源选项,该选项会在需要显示资源的时候,才会去加载这个资源。大部分情况下可以勾选上,减少加载时间,避免加载时加载大量暂时用不到的资源。

  • 资源批量加载优化

在实际项目中我们经常会遇到一些需要大量生成节点或者prefab的情况,例如子弹、怪物等等。

在生成时,如果不进行优化,很容易造成瞬间的内存飙升,从而带来游戏感受上的卡顿。

通常我们可能会使用这样的代码:

 for (let i = 0; i < 200; i++) {      var node = new cc.instantiate(this.prefab);      node.parent = this.layout; }

当需要批量生成的数量不多时,不会对我们的效果有太大的影响,但当数量到一定程度,例如批量生成200个时,卡顿带给用户的体验会很糟糕。

参考demo工程中的loadScene场景。我们可以看到卡顿时,一帧的耗时达到了180+ms。

公众号回复:“参考demo”,获得下载链接

LazyAn-—CocosCreator优化系列(一):加载优化_第21张图片

对于这种情况我的建议是,不要在同一帧中做大量的实例化操作,避免内存的突然飙升。

实际的解决办法有很多,比如使用schedule,setTimeOut等等。这里给大家推荐一个比较好的方法:

借用第三方库async。

async.eachLimit(array,  5,  (index,cb)  =>  {      var node = new cc.instantiate(this.prefab);      node.parent = this.layout;      setTimeout(cb,  0); });

使用的代码很简单,async的eachLimit方法可以帮助我们限制每一帧实例化的数量,同时在表现效果上面与其他方法相同,同时表现更流畅,无卡顿,代码也相对比较干净。

在项目中使用async很简单。

在项目目录下打开命令行工具

执行npm init,生成package.json

npm init

然后执行npm install async --save

npm install async --save

LazyAn-—CocosCreator优化系列(一):加载优化_第22张图片

这样就安装好async模块了。

 

接下来在项目中通过require,即可使用async库

var async = require("async");

你可能感兴趣的:(cocoscreator,cocos-creator)