要點一:
文件格式與像素格式的區別:文件格式是圖像爲了存儲信息而使用的對信息的特殊編碼方式,大都通過了壓縮,它存儲在磁盤或內存中,可是並不能被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紋理