相關閱讀 |
>>> 技術話題—商業文明的嶄新時代 >>> | 簡體 傳統 |
在IOS上,圖片會被自動縮放到2的N次方大小。比如一張1024*1025的圖片,占用的內存與一張1024*2048的圖片是一致的。圖片占用內存大小的計算的公式是;長*寬*4。這樣一張512*512 占用的內存就是 512*512*4 = 1M。其他尺寸以此類推。(ps:IOS上支持的最大尺寸為2048*2048)。
Cocos2d-x 在構造一個精靈的時候會使用spriteWithFile或者spriteWithSpriteFrameName等 無論用哪種方式,cocos2d-x都會將這張圖片加載到緩存中。如果是第一次加載這個圖片,那就會先將這張圖片加載到緩存,然后從緩存讀取。如果緩存中已經存在,則直接從緩存中提取,免除了加載過程。
圖片的緩存主要由以下兩個類來處理:CCSpriteFrameCache, CCTextureCache
CCSpriteFrameCache加載的是一張拼接過的大圖,每一個小圖只是大圖中的一個區域,這些區域信息都在plist文件中保存。用的時候只需要根據小圖的名稱就可以加載到這個區域。
CCTextureCache 是普通的圖片緩存,我們所有直接加載的圖片都會默認放到這個緩存中,以提高調用效率。
因此,每次加載一張圖片,或者通過plist加載一張拼接圖時,都會將整張圖片加載到內存中。如果不去釋放,那就會一直占用著。
不要以為,計算內存時,只計算加載到緩存中的內存就可以了。以一張1024*1024的圖片為例。
CCSprite *pSprite = CCSprite::spriteWithFile("a.png");
調用上邊這行代碼以后,可以在LEAKS工具中看到,增加了大約4M的內存。然后接著調用
addChild(pSprite);
這時,內存又增加了4M。也就是,一張圖片,如果需要渲染的話,那它所占用的內存將要X2。
再看看通過plist加載的圖片,比如這張大圖尺寸為2048*2048。想要加載其中的一張32*32的小圖片
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("b.plist");
此時內存增加16M (汗)
CCSprite *pSpriteFrame = CCSprite::spriteWithSpriteFrameName("b1.png");
b.png 大小為32*32 ,想著也就是增加一點點內存,可實際情況是增加16M內存。也就是只要渲染了其中的一部分,那么整張圖片都要一起被加載。
但是情況不是那么的糟糕,這些已經渲染的圖片,如果再次加載的話,內存是不會再繼續升高的,比如又增加了100個b.plist的另一個區域,圖片內存還是共增加16+16 = 32M,而不會繼續上升。
如果游戲有很多場景,在切換場景的時候可以把前一個場景的內存全部釋放,防止總內存過高.
CCTextureCache::sharedTextureCache()->removeAllTextures(); 釋放到目前為止所有加載的圖片
CCTextureCache::sharedTextureCache()->removeUnusedTextures(); 將引用計數為1的圖片釋放掉CCTextureCache::sharedTextureCache()->removeTexture(); 單獨釋放某個圖片
CCSpriteFrameCache 與 CCTextureCache 釋放的方法差不多。
值得注意的是釋放的時機,一般在切換場景的時候釋放資源,如果從A場景切換到B場景,調用的函數順序為B::init()---->A::exit()---->B::onEnter() 可如果使用了切換效果,比如CTransitionJumpZoom::transitionWithDuration這樣的函數,則函數的調用順序變為B::init()---->B::onEnter()---->A::exit() 而且第二種方式會有一瞬間將兩個場景的資源疊加在一起,如果不采取過度,很可能會因為內存吃緊而崩潰。
有時強制釋放全部資源時,會使某個正在執行的動畫失去引用而彈出異常,可以調用CCActionManager::sharedManager()->removeAllActions();來解決。
優化的心得就是盡量去拼接圖片,使圖片邊長盡可能的保持2的N次方并且裝的很滿。但要注意,有邏輯關系的圖片盡量打包在一張大圖里,另外一點就是打包的時候要考慮到層的分布。因為為了渲染效率可能會用到CCSpriteBatchNode;同一個BatchNode里的圖片都是位于一個層級的,因此必須根據各個圖片的層級關系,打包到不同的plist里。有時內存和效率不可以兼得,只能盡量平衡了。
最后附一個各代IOS設備的內存限制情況
設備 建議內存 最大內存
iPad2/iPhone4s/iphone4 170-180mb 512mb
iPad/iPod touch3,4/iphone3gs 40-80mb 256mb
iPod touch1,2/iPhone3g/iPhone1 25mb 128mb
上述建議內存只是一些人自己測試的結果,可用的RAM不大于最大內存的一半,如果程序超過最大內存的一半,則可能會掛掉。
另外在LEAKS里查看模擬器中和真機總的內存,會有較大出入。在模擬器中的結果與實際更接近一些。
做個筆記用
姚康 2013-08-31 21:40:36
稱謂:
内容: