Cocos2dx游戏优化总结

独立开发游戏不容易,初期的立项,中期是功能开发与方案修改的死循环,到后期资源的优化、代码加密等。现在把踩过的坑,和做过的事记录下来,一方面给自己做个记录,好记性不如烂笔头,另一方面也希望能够帮助到大家。

下面整理的知识,有一些是开发过程中注意到的,有一些是之前没注意,但是到了后期需要的时候上网查资料,请教别人之后整理的。


一、初期需要规划好资源目录

Cocos2dx游戏优化总结_第1张图片



二、选择图片格式

android一般使用png,ios一般使用pvr。

png是一种无损压缩,读取时会先解压,这时候会出现内存翻倍的情况。

pvr可以被显卡所认可,而不需要开辟临时内存来读取,所以即便是RGBA8888格式的图片,pvr也会比png更有效率,虽然最终纹理的内存大小是一样的,但是可以避免加载时内存的暴涨。

pvr.ccz其实就是pvr图片zip打包的,程序读pvr.ccz的时候,会先解压成pvr,然后再去pvr生成纹理。这里比直接读取pvr多了一步解压,但是pvr.ccz的图片大小远小于pvr,所以可以极大减少包体的体积。

pvr既然这么好,那为什么android不适用pvr呢?

其实现在已经有一部分安卓机型支持pvr,但是由于不是全部,所以android统一使用png。

由于pvr.ccz能极大减少包体体积,而且解压成pvr时也不会消耗太多,所以ios统一使用pvr.ccz。


下面是我自己测试一个例子:

这是一张图片在texturepacker显示的尺寸。

Cocos2dx游戏优化总结_第2张图片

导出三种pvr格式和png格式,发现skill.pvr跟texturepacker的大小是一样。


可以发现,当加载成纹理时,纹理大小跟pvr的大小也是一样的。



三、使用Texturepacker打包小图

打包小图的好处就是节省内存空间、提高载入速度,往往把小图拼接成一张大图,一次载入,减少I/O次数。

打包规则:

1、全局资源打在一起。某些小图片长期使用,比如玩家头像,归属全局资源,大图plist资源加载之后常驻内存。

2、特定界面资源。比如说设置界面,只有在特定的时候玩家才会打开,把这些ui图片打包成plist,打开界面是加载,关闭界面时释放。

3、大图的尺寸不要超过2048*2048。

4、POT或者NPOT。这个网上的说辞不一,有的说对png来说NPOT能提高效率,对pvr却不能提高,有的又说都能提高效率。这个我也不清楚。选择NPOT可以减少导出图片体积,相应的纹理缓存也会减少。比如一张图片NPOT导出是900x900,加载的纹理大小也是900x900,但是Opengl渲染所用的纹理一定是1024*1024,也就是2的幂次方,至于什么时候从900x900扩张为1024*1024,我也不清楚。而我是选用了NPOT。



四、资源预加载

玩家可以接受进入场景是加载场景的等待,但接受不了游戏过程中的卡顿,所以预加载是有必要的。

图片资源异步加载:cc.Director:getInstance():getTextureCache():addImageAsync()。

动画资源异步加载:ccs.ArmatureDataManager:getInstance():addArmatureFileInfoAsync()。

这里需要注意的是,不要在一个for循环调用异步加载接口,否则会溢出。应该一个加载完了,再开始异步加载下一个。


及时清除某些不常用的纹理缓存也是需要的。比如我们游戏打开时有logo闪屏界面,有loading主界面,这里面用到的图片在正式进入游戏之后就不再使用,如果不清除纹理缓存,那么就会常驻内存。所以使用完之后就立马清除纹理缓存。




五、资源优化

主要是从包体体积和纹理大小两方面入手。

1、使用textuerpacker打包时选择NPOT可以减少图片大小和纹理大小。


2、不管png图片存储时选择的是png8还是png24,加载成纹理时都以RGBA8888的格式,RGBA8888也是cocos2d-x默认的纹理格式。如果图片没有透明,那么可以选用RGB565,比如背景图片,或者矩形的ui按钮等。有透明通道的可以选用RGBA4444。这样的好处就是可以同时减少图片大小和纹理大小。


 比较上面两张图片,肉眼看不出有任何区别,第一张是以RGBA8888保存的,大小12.5KB。第二张是以RGBA4444保存的,大小7.03KB。


转格式用的是Texturepacker。


如果有透明通道选择FloydSteinbergAlpha,RGB565格式也就是没有透明通道选择FloydSteinberg。这个是tp提供的抖动算法,我也不懂,但是勾选了效果确实不错。


当然,这个转格式不是一成不变的,根据需要去转,如果一些资源转了会变型就还是用RGBA8888。

这里有个小坑,png图片不管以什么格式保存,加载到内存都会以RGBA8888的格式,而pvr保存时用什么格式加载的时候就用什么格式。CCTextuer2D类提供了一个静态接口可以设置默认的加载纹理格式setDefaultAlphaPixelFormat(),加载png时我们可以调用这个方法设置纹理格式,完了之后再调用这个方法还原原来的纹理格式。比较蛋疼,还是pvr好。

Texture2D::setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGBA4444);

//加载图片

Texture2D::setDefaultAlphaPixelFormat(Texture2D::PixelFormat::RGBA8888);


3、用cocostudio编辑动画导出的png一般都是2的幂次方,可以自己用tp打包后替换。

Cocos2dx游戏优化总结_第3张图片


替换之后:

Cocos2dx游戏优化总结_第4张图片


可以看出,虽然图片大小没有改变多少,但是纹理占用却是3倍之差。


这里解释一下为什么会这样。

首先png压缩方式使用的是索引色,存储图像前会先判断图像上哪些地方是相同的哪些地方是不同的,为此需要在图像上所有出现的颜色进行索引,把这些颜色变成索引色。索引色就好比绘制这幅图像的调色板,png显示图像时则用调色板上的这些颜色去填充相应的位置。因为两张图片除了大小基本一样,所以索引色也就一样,4k的差距估计是空白区域的颜色标记。

但是加载到纹理时会先对png解压缩,然后如果是RGBA8888的格式,则每个像素点占4个字节,所以每张纹理的大小是width * height * 4。如果尺寸是1024x128,那么纹理大小就是1024x128x4=512kb。


4、合理使用缩放。

我们的游戏背景图是640x1170的,渲染时则会扩充为1028x2048,这里会浪费好大的空间。而我的改进方法是把图片等比缩小为500x914,使用的时候再放大到640x1170,这时候扩充的大小为512x1028,小了整整一半。再把纹理格式改为RGB565保存。这样改了之后效果没多大的差别,而且背景图片也不是关注的重点。

你可能感兴趣的:(Cocos2d-x)