ocos2d-x基礎知識(九)cocos2d-x場景切換時記憶體過高導致crash 解決方法
最近在做一個cocos2d-x的專案時,遇到一個問題,就是在pc上執行都是ok的,可是在ipad和andriod上面,在場景切換時時常會掛掉,用蘋果自帶的Instruments工具檢測時,發現在場景正常執行時,記憶體大概保持在三四十兆,但是在場景切換時,一瞬間會達到七八十兆,遇到一些素材比較多或者層比較多的場景,則會達到一百多兆。大家知道在ipad1上面,記憶體最大是128M,那麼這個程式如果在ipad1上面執行,肯定會經常掛掉。遇到問題,只能一步步分析,一步步找。
(1)先把所有場景的retain的東西檢查一遍,看看在onExit的時候有沒有release掉,這個檢查完以後,還是會crash,所以這種情況不是根源。
(2)對於有好幾個層的場景,在init的時候,先載入第一個層的,而不是把所有層的東西全部載入完,在切換層的時候再載入相對應的層,這種方法果然有效,當切換到這個場景的時候,記憶體果然減少了一半左右。但是對於只有一個層的場景來說,在切換時也是會掛,所以問題還沒有找完全。
(3)我們知道,在每個場景裡面會有一個init函式,一個onEnterTransitionDidFinish函式,一個Onexit函式,init實現一些初始化工作,onEnterTransitionDidFinish在init之後執行,Onexit在場景退出時回收init時分配的資源。在除錯時發現一個很有趣的現象,那就是從場景一切換到場景二時,在切換的一瞬間會記憶體會非常高,但是過了一段時間後,記憶體會回到一個平穩的狀態,譬如切換時記憶體會達到80M,切換過後記憶體會降到50M。分析原因,懷疑是上一個場景的記憶體還沒有釋放,然後這一個場景的記憶體已經分配,所以兩個疊加在一起,就比較高了。所以我便在第一個場景的Onexit函式中加一個斷點,在第二個場景的init和onEnterTransitionDidFinish函式中各加一個斷點,然後執行程式,發現程式先到第二個場景的init中,然後再回到第一個場景的Onexit中,最後才到第二個場景的onEnterTransitionDidFinish中。我才恍然大悟,原來在場景切換時,不是馬上會執行第一個場景的Onexit函式,而是先到第二個場景的init中載入資源,然後回到第一個場景中釋放資源,最後才是到onEnterTransitionDidFinish中。
最終解決方法:
把一些資源的初始化放到onEnterTransitionDidFinish中進行,那麼究竟應該把那些資源放到onEnterTransitionDidFinish中初始化,而那些資源又只能放到init中呢?
(1)像背景圖這種只能放到init中,像場景切換時要看到的一些精靈,必須放到init中,不然場景切換時會看不到背景或者一些精靈。
(2)象精靈的一些動畫,動作,可以放到onEnterTransitionDidFinish中來初始化。
舉個例子:
譬如一隻船在划動,那麼船這隻精靈在場景切換時要展示,所以必須放在init中
//小船精靈的載入
m_boatAction = CCSprite::spriteWithFile(s1_little_boat1);
addChild(m_boatAction);
m_boatAction->setPosition( CCPointMake(s.width/2, s.height/2+130));
m_boatAction->setScale(0.3);
m_boatAction->retain();
而船划動的動作,就可以放到onEnterTransitionDidFinish來初始化和執行
CCSize s = CCDirector::sharedDirector()->getWinSize();
CCAnimation* animation = CCAnimation::animation();
char frameName[100] = {0};
for( int i=1;i<=5;i++)
{
sprintf(frameName, "scene1/little_boat%d.png", i);
animation->addFrameWithFileName(frameName);
}
CCActionInterval* action = CCAnimate::actionWithDuration(2, animation, false);
repeatAction = CCRepeatForever::actionWithAction(action);
repeatAction->retain();
通過這三步,基本上就可以避免在場景切換時記憶體過而導致crash的情況
快取釋放
如果遊戲有很多場景,在切換場景的時候可以把前一個場景的記憶體全部釋放,防止總記憶體過高.
CCTextureCache::sharedTextureCache()->removeAllTextures(); 釋放到目前為止所有載入的圖片
CCTextureCache::sharedTextureCache()->removeUnusedTextures(); 將引用計數為1的圖片釋放掉CCTextureCache::sharedTextureCache()->removeTexture(); 單獨釋放某個圖片
CCSpriteFrameCache 與 CCTextureCache 釋放的方法差不多。
場景的切換:
值得注意的是釋放的時機,一般在切換場景的時候釋放資源,如果從A場景切換到B場景,呼叫的函式順序為
1、如果沒有切換效果,則為B的init(),A的onExit(),B的onEnter()
2、如果有切換效果,則為B的init(),B的onEnter(),A的onExit()
有時強制釋放全部資源時,會使某個正在執行的動畫失去引用而彈出異常,可以呼叫CCActionManager::sharedManager()->removeAllActions();來解決。
摘自:[url]http://blog.csdn.net/zhangjingyangguang/article/details/7618048[/url]
相關文章
- Java基礎知識_記憶體Java記憶體
- node記憶體基礎知識記憶體
- cocos2d-x 場景動畫切換過渡大全動畫
- Android-Fragment 切換造成記憶體溢位,導致記憶體增長AndroidFragment記憶體溢位
- 實體記憶體過高怎麼辦 實體記憶體使用率高的解決方法記憶體
- 電腦記憶體佔用過高怎麼辦 電腦記憶體佔用過高解決方法記憶體
- 基礎知識1——例項記憶體結構記憶體
- ECS記憶體佔用高導致wordpress資料庫經常掛掉的兩種解決方法記憶體資料庫
- 解決記憶體溢位九法記憶體溢位
- win10記憶體佔用高解決方法Win10記憶體
- 解決NSTimer迴圈引用導致記憶體洩漏的六種方法記憶體
- Objective-C 基礎一:物件導向過程基礎知識Object物件
- Java&Android 基礎知識梳理(3) 記憶體區域JavaAndroid記憶體
- 圖片基礎知識梳理(2) Bitmap 佔用記憶體分析記憶體
- 基於多種場景DataGuard切換方案
- 遊戲基礎知識——碼頭場景的設計手法遊戲
- 遊戲基礎知識——“隱居住所”場景的設計遊戲
- 遊戲基礎知識——“中心城市”場景的設計遊戲
- Linux下php-fpm程式過多導致記憶體耗盡問題解決LinuxPHP記憶體
- mysql佔用記憶體高的一種解決方法MySql記憶體
- 遊戲基礎知識——“垃圾站”場景的設計手法遊戲
- 遊戲基礎知識——遺蹟場景的設計特點遊戲
- 啃碎併發(九):記憶體模型之基礎概述記憶體模型
- JavaSE基礎知識之修飾符和使用場景,你真的瞭解嘛Java
- 【知識分享】導致伺服器網路速度延時高的原因伺服器
- Azure Data Factory(九)基礎知識回顧
- Latch導致MySQL CrashMySql
- 解決記憶體設定過大導致例項無法啟動ORA-27100記憶體
- 專案中多次操作SharedPreferences導致ANR場景的解決
- 遊戲基礎知識——“載具內部”場景的設計手法遊戲
- Java基礎知識七——方法Java
- 九、JVM記憶體模型詳解JVM記憶體模型
- win10電腦記憶體過高怎麼辦 win10記憶體佔用過高的方法Win10記憶體
- SQLL基礎知識記錄SQL
- mysql小記--基礎知識MySql
- 記錄佇列序列化模型導致的記憶體溢位的解決方案佇列模型記憶體溢位
- 用JAVA轉換簡繁體的基礎知識 (轉)Java
- Android記憶體洩漏場景Android記憶體