cocos2dx 中切換場景內存佔用過高的處理

cocos2dx 中切換場景內存佔用過高的處理

1、運行場景:

CCScene *pScene = HelloWorld::scene();
pDirector->runWithScene(pScene);

2、替換場景:

(1)

CCScene *pScene=SceneTestScene::scene();
CCDirector::sharedDirector()->replaceScene(pScene);

(2)
CCScene *pScene=SceneTestScene::scene();
CCDirector::sharedDirector()->pushScene(pScene);
(3)
CCScene *pScene=SceneTestScene::scene();
CCDirector::sharedDirector()->popScene(pScene);
3具體的代碼執行流程

假設scene A是活動場景,現在我們用scene B來pushScene替換A,A和B的生命週期是這樣的:

B ---- init();

A ---- onExit();

B ---- onEnter();

B ---- onEnterTransitionDidFinish();

此時popScene,彈出scene B,函數調用如下:

B ---- onExit();

B ---- 析構函數被調用

A ---- onEnter(); (並不會執行sceneA的init函數 ,因爲 pushScene的時候會執行sceneA的onExit函數釋放一些資源, 當pop的時候,不會執行init函數加載需要的資源,出現爲止的錯誤

從上面可以看出以下幾點,

1. A的析構函數始終未被調用,因此A一直在內存中。

2. 先執行B的init()函數,之後才調用A的onExit()方法,再之後才調用B的onEnter();所以初始化最好應該放在init中來初始化。在上一個場景退出之前初始化好後一個場景需要的資源。(內存佔用過高出現在這裏

同樣的,我們再來看一下replaceScene切換場景,scene的生命週期

假設scene A是活動場景,現在我們用scene B來replaceScene替換A,A和B的生命週期是這樣的:

B ---- init();

A ---- onExit();

A ---- 析構函數被調用

B ---- onEnter();

B ---- onEnterTransitionDidFinish();


此時B replace A回來的調用跟上面一樣,如下:

A ---- init();

B ---- onExit();

B ---- 析構函數調用

A ---- onEnter();



4具體的引擎的執行代碼, 查看對象的生命週期。見下面的鏈接
http://blog.csdn.net/tonny_guan/article/details/28121973

-----------------華麗的分割線----------------
當使用replaceScene切換場景的時候,在遊戲所佔有的內存是當前內存峯值時多少哪,很可怕的 時當前場景的內存值,加上下一個場景的資源所佔用的內存值。
原因。。。。
在每個場景裏面會有一個init函數,一個onEnterTransitionDidFinish函數,一個Onexit函數,init實現一些初始化工作,onEnterTransitionDidFinishinit之後執行,Onexit在場景退出時回收init時分配的資源。在調試時發現一個很有趣的現象,那就是從場景一切換到場景二時,在切換的一瞬間會內存會非常高,但是過了一段時間後,內存會回到一個平穩的狀態,譬如切換時內存會達到80M,切換過後內存會降到50M。分析原因,懷疑是上一個場景的內存還沒有釋放,然後這一個場景的內存已經分配,所以兩個疊加在一起,就比較高了。所以我便在第一個場景的Onexit函數中加一個斷點,在第二個場景的initonEnterTransitionDidFinish函數中各加一個斷點,然後運行程序,發現程序先到第二個場景的init中,然後再回到第一個場景的Onexit中,最後纔到第二個場景的onEnterTransitionDidFinish中。我才恍然大悟,原來在場景切換時,不是馬上會執行第一個場景的Onexit函數,而是先到第二個場景的init中加載資源,然後回到第一個場景中釋放資源,最後纔是到onEnterTransitionDidFinish中。    內存中的峯值很驚人。
方案一, 將必要的資源放在onEnter 中處理,其他的資源 放在onEnterTransitionDidFinish處理。
方案二 , 給場景切換添加一個過度場景,現在主流的rpg ,或者橫版格鬥的遊戲都已經這樣處理。 因爲資源量比較大,這樣處理高效並且安全。

--總結

1. 切換全屏場景的時候最好使用replaceScene而不是pushScene。

因爲pushScene並不會銷燬前一個scene,僅僅是將後一個scene按照堆棧的方式加入到前一個scene的上面。如果自身代碼中內存管理寫的不好的,利用pushScene很難發現該方面的問題,一旦崩潰定位都很難定位。replaceScene可以及早的將隱含的問題給暴露出來。

2. 儘量不要在onEnter裏面初始化精靈Sprite

這個就和上一條有點關係了,如果使用了pushScene,那麼再popScene的時候是不會調用前一個場景的init方法的(上一個界面的資源有的已經釋放,這時出現未知的錯誤),所以有同學就喜歡把一些初始化放在onEnter裏面,具體爲什麼不好,我們來看一下不同切換場景的時候,每個Scene的生命週期就知道了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章