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();来解决。
摘自:http://blog.csdn.net/zhangjingyangguang/article/details/7618048
相关推荐
Cricket 2020-05-31
woxmh 2019-12-30
CaptainCTR 2019-12-19
86463960 2013-07-15
80487916 2013-07-06
86463960 2013-08-28
BenOnceMore 2013-08-26
89741733 2014-03-20
86201242 2014-05-13
85427010 2014-09-04
文艺小青年 2015-03-26
cooclc 2015-03-26
85427010 2015-05-22
frankwang 2015-05-19
80487916 2015-05-18
进入场景而且过渡动画结束时候触发。提示 GameScene场景中的继承于节点,这些生命周期事件根本上是从Node继承而来。事实上所有Node对象都有这些事件,具体实现代码与GameScene场景类似。
87921036 2015-05-12
85427010 2011-12-31
yizhiyanstart 2011-12-31