要点一:
文件格式与像素格式的区别:文件格式是图像为了存储信息而使用的对信息的特殊编码方式,大都通过了压缩,它存储在磁盘或内存中,可是并不能被GPU所识别(jpg,png…),这些图片格式当被游戏读入后,还须要通过CPU解压成像素格式,如:RGBA8888,再传送到GPU端进行使用。
而像素格式是能被GPU所识别的,能被快速寻址并采样。android
要点二:
图片自己大小和其所占内存大小是两码事。这就比如一个zip压缩包使用时要解压还原数据,这个zip文件就比如图片自己,而解压后的文件就比如图片所占内存大小。纹理自己大小主要看咱们选用什么样的压缩格式和压缩比,而所占内存大小就只由两个因素决定:1,图片的像素点个数(分辨率) 2,单位像素占用的字节数(像素格式)。即纹理内存大小 = 纹理长度 * 纹理宽度 * 单位像素占用的字节数,如:一张1136x640的RGBA8888的png图片占用的内存为 1136x640x4 = 2.8M左右。
注:cocos引擎中,对于大的背景图咱们通常使用jpg文件格式,jpg压缩比更大,是有损压缩,而像素格式使用16位的RGB565格式。可是它占内存大小就不是咱们使用的RGB565 16位格式了,cocos会自动把它转换为RGBA8888 32位格式解析。最终决定图片占用内存的是它的像素格式和尺寸,与其扩展名无关。png八、png3二、jpg、pvr只要其像素格式都是rgba8888,那么最终图片占用的内存是同样的。ios
要点三:
在cocos中,谈谈不一样纹理实际加载过程当中内存变化,先以一张1024*1024 自己大小500k的jpg/png图片为例:
1,读取图片文件(500k)
2,把jpg/png数据最终都是按RGBA8888(默认)格式解析(4mb)
3,释放500k的图片内存
4,上传给OpenGL纹理数据(4mb)
5,释放4mb内存
注意,这个过程不是必然的顺序执行,释放内存实际是由系统决定的,会很快,可是不必定是当即执行。 因此内存会瞬间飙升到8.5mb左右,而后减小5mb,稳定到4mb左右,这么一个过程变化。这就是咱们常说的“间歇性内存飙高”。算法
而pvr格式显卡直接支持,加载速度天然要快,不须要开辟临时内存来读取pvr图片,节约了解析图片数据到纹理这一步的消耗(第2步)。也就是说读取一样像素格式的pvr资源(通常用pvr.ccz压缩格式)消耗4mb,将pvr图片数据提交给显卡消耗4mb。而后释放文件数据4mb。这么看彷佛跟Png从内存占用上相比也没什么优点。可是若是像素格式用的是RGBA4444那就有很大优点了,内存少一半。而前面的那种自身无论用什么格式,最终cocos都会把它们的格式统一默认转换为32位的RGBA8888再上传GPU。
注释:
1,pvr.ccz其实就是pvr图片zip打包下,程序读的时候要先解压出pvr资源,而后再读取pvr。不过因为压缩下能够极大的减少图片体积,因此虽然多了解压过程也不会有特别多的cpu消耗,通常咱们都是推荐选择pvr.ccz的。
2,当加载jpg、png这样的纹理时,在短时候内,它会消耗约两倍于(jpg3倍,多jpg到png转换过程)它自己内存占用的内存大小。这个告诉咱们这样的纹理最好不要一帧内连续加载,最好分散到多帧去完成,由于每帧cocos都会自动回收一次内存,对于这些中间建立的纹理内存会自动释放,从而避免一帧里内存不至于飙过高。
3,按照纹理size从大到小的顺序加载纹理,因为加载纹理时额外的内存消耗问题,因此,采用按纹理size从大到小的方式来加载纹理是一个最佳实践。假设,你有一个占内存16MB的纹理和四个占用内存4MB的纹理。若是你首先加载4MB的纹理,这个程序将会使用16MB的内存,而当它加载第四张纹理的时候,短期内会飙到20MB。这时,你要加载16MB的那个纹理了,内存会立刻飙到48MB(4*4 + 16*2),而后再降到32MB(4*4 + 16)。可是,反过来,你先加载16MB的纹理,而后短时候内飙到32MB。而后又降到16MB。这时候,你再依次加载剩下的4个4MB的,这时,最多会彪到(4*3 + 4*2 + 16=36)MB。在这两种状况下,内存的峰值使用相差12MB,要知道,可能就是这12MB会断送你的游戏进程的小命。缓存
1,jpg压缩比最高,质量较好,可是不支持半透明(通常用于背景图)。
二、png8一样图片会比jpg略大一些,使用ImageAlpha进行转换,视觉上几乎看不出差异。
注: 这两种图片格式均可以极大的减小图片体积(减小70%~80%),可是无助于减小内存。框架
1,尽可能使用颜色深度为16bit的图片。cocos上经过cc.Texture2D.setDefaultAlphaPixelFormat(cc.Texture2D.PIXEL_FORMAT_RGBA4444)改变默认像素格式,但若是图片自己的颜色深度是32位,转换成RGBA4444后,则可能会使图片失真,看起来就很模糊。这个能够经过TexturePacker工具中开启抖动算法获得改善(模糊处颜色混合处理)。特别是在拥有Retina显示的像素密度下,你几乎看不出16位与32位的纹理之间的差异。工具
2,碎图打大图时,使用NPOT纹理,NOPT是“non power of two”的缩写,译做“不是2的幂”。若是纹理图集(texture atlas)使用NPOT的纹理,它将有一个具大的优点:它容许TexturePacker更好地压缩纹理。所以,咱们会更少地浪费纹理图集的空白区域。并且,这样的纹理在加载的时候,会少使用1%到49%左右的内存。字体
3,使用pvr格式纹理。由于jpg是没有透明色的,一个像素最多3字节,而png一个像素4字节,jpg纹理应该占用内存更小才对,可是cocos最终把纹理都会转换成rgba8888格式,因此不管是jpg仍是png,一个像素占用的都是4字节。正因cocos2d对其余纹理支持不够好,pvr才会显得那么高效。pvr也不是万金油。pvr图像是专门为ios设备上面的powerVR图形芯片指定的图形容器,能够直接加载到显卡上,而不需通过中间的转化。虽然android设备下可使用pvr格式,可是不能使用pvrtc4(一个像素只占4bit),但愿经过pvr像ios设备上同样真正减小游戏内存是不太可行的。优化
4,android上最省内存纹理固然是ETC(一个像素占4bit),不过ETC1没有alpha通道,须要咱们额外经过一些简单shader实现(一样大小的遮罩图作颜色混合)。不过如今最新的ETC2能够直接支持alpha通道了,并且效果更好,可是须要opengles3.0支持,考虑到2.0设备的市场占有率,通常使用ETC1。编码
人生之因此纠结,在于许多事情你能够选择。上面的纹理格式,同一种状况下,可能多种都适合,那如何选择呢!咱们仍是根据具体状况而定:
一、场景、背景、全屏图片
2D手机游戏中,多半都有这样的图片,以做为背景,特别在一些SLG,横版过关游戏中。这种图片对ALPHA没有要求,而且,在同一时间,只会出现一张(若是是多张拼接,也不会超过屏幕尺寸太多),内存不会成为关键点。因此,在这种状况下,咱们大胆选择JPG就能够了。orm
二、场景的前景,装饰物,可移动对象(npc,moster,…)
这种要看规模,若是规模较小,类型很少。 或者类型虽然多,但同一时间出如今场景中的类型很少,那咱们能够选择压缩PNG8的方式,它支持ALPHA通道,文件又小。若是同屏可能出现多种这种,则须要考虑在IOS上使用PVRTC,在ANDROID上使用ETC1+ALPHA_MASK。实际上,为了好维护,通常都是统一用pvr.ccz打包。
三、UI
UI的背景图,能够优先考虑使用压缩PNG8,若是达不到精度要求,则使用PNG32。而对于UI的小元素,能够考虑使用压缩PNG8.
对于UI的图标,通常是不带ALPHA的PVRTC/ETC + 一张公共的ALPHA掩码图,经过双层混合来实现圆边效果。 由于图标同屏出现可能较大。 若是图标可以控制在必定范围内,因为图标是48X48等大小,一张1024x1024的大图,能够放400个图标。 换用JPG,也有4MB的开销,若是这个是能够接受的,也可使用JPG+ALPHA_MASK的方式。
写到这里才发现,其实只须要下面一句话就能够搞定。
这类图片会不会同时出现多个,同时出现时,内存开销是否没法接受, 若是确实没法接受,则使用GPU纹理,不然,优先考虑JPG,JPG+ALPHA,或者PNG8。就是说,首先要减少安装包大小,若是内存有没法接受的状况,才须要用GPU纹理进行优化。
游戏内存优化咱们通常能够从这么3个方面入手:引擎自身提供的优化选项,引擎底层框架,语言上层(内存泄漏)。
下面是一些经常使用手段:
首先看纹理优化,为了优化纹理内存使用,必须知道什么因素对纹理内存使用的影响最大。主要有3个因素会影响纹理内存,即纹理格式(压缩仍是非压缩)、颜色深度和大小。咱们可使用PVR格式纹理减小内存使用。推荐纹理格式为pvr.ccz。纹理使用的每种颜色位数越多,图像质量越好,可是越耗内存。因此咱们可使用颜色深度为RGB4444的纹理代替RGB8888,这样内存消耗会下降一半。此外超大的纹理也会致使内存相关问题。因此最好使用中等大小的纹理。
音频优化,3个因素会影响音频文件的内存使用,即音频文件数据格式、比特率及采样率。推荐使用MP3数据格式的音频文件,由于Android平台和iOS平台均支持MP3格式,此外MP3格式通过压缩和硬件加速。背景音乐文件大小应该低于800KB,最简单的方法就是减小背景音乐时间而后重复播放。音频文件采样率大约在96-128kbps为佳,比特率44kHz就够了。
字体和粒子优化,在此有两条小提示:使用BMFont字体显示游戏分数时,请尽量使用最少数量的文字。例如只想要显示单位数的数字,你能够移除全部字母。至于粒子,能够经过减小粒子数来下降内存使用。
提示与技巧: 一、一帧一帧载入游戏资源 二、减小绘制调用,打包大图 三、载入纹理时按照从大到小的顺序 四、避免高峰内存使用 五、使用载入屏幕预载入游戏资源 六、须要时释放空闲资源 七、收到内存警告后释放缓存资源 八、使用纹理打包器优化纹理大小、格式、颜色深度等 九、使用JPG格式要谨慎! 十、请使用RGB4444颜色深度16位纹理 十一、请使用NPOT纹理,不要使用POT纹理 十二、避免载入超大纹理 1三、推荐1024*1024 NPOT pvr.ccz纹理集,而不要采用RAW PNG纹理