• cocos2dx 3.3 场景切出时RenderTexture crash


    在cocos2dx 3.3中下面myScene在切出时会存在概率性崩溃(代码作了最大程度简化,仅为说明问题):

    class CmyLayer:public Layer{

    public:

      CmyLayer(){

        m_sprite=NULL;

        m_renderTex=NULL;

      }

      virtual~CmyLayer(){

      }

      bool init(){

        m_sprite=Sprite::create("a.png");

        this->addChild(m_sprite);

        m_renderTex=RenderTexture::create(w,h);

        this->addChild(m_renderTex);

        

        return true;

      }

      void udpate(float dt){

        m_renderTex->begin();

        m_sprite->visit();

        m_renderTex->end();  

      }

    private:

      RenderTexture* m_renderTex;

      Sprite* m_sprite;

    };

    class CmyScene:public Scene{

    public:

      CmyScene(){

      }

      virtual~CmyScene(){

      }

      bool init(){

        CmyLayer*myLayer=new CmyLayer();

        myLayer->autorelease();

        myLayer->init();

        addChild(myLayer);

        return true;

      }

    };

    在myScene场景切出时概率性地崩溃在两个位置:

    (1)RenderTexture的onBegin函数里,在RenderTexture的实现中onBegin是作为customCommand发出去的。

    (2)崩溃在RenderTexture的GroupCommand里。

    其中第一个崩溃位置出现频率占大多数。

    崩溃在command里是最坑爹的,因为其执行是异步的,所以当崩溃时很难调查对象在发出此command时的当时状态,甚至连发出command的对象是谁都很难知道!数据/状态一致性问题和debug困难是我讨厌command机制的主要原因。

    先停止吐槽,猜测崩溃原因,认为很可能是在场景切出时由于m_renderTex随myLayer一起销毁,但m_renderTex发出的customCommand已加入到command队列且尚未执行,这样当等到此customCommand执行时,它会调用m_renderTex的onBegin函数,但m_renderTex已销毁,所以产生不可预料的结果。

    为了避免“对象已销毁但其customCommand已发出却尚未执行”而导致的“调用对象不存在”的情况出现,我尝试采取了下面两个措施:

    1,在场景切出时尽早停止CmyLayer::update。(因为崩溃的customCommand是在CmyLayer::update的m_renderTex->begin()中发出的)

    2,在场景切出时推迟销毁m_renderTex。

    具体地,CmyLayer代码改成:

    class CmyLayer:public Layer{

    public:

      CmyLayer(){

        m_sprite=NULL;

        m_renderTex=NULL;

      }

      virtual~CmyLayer(){

        if(m_renderTex)m_renderTex->autorelease();//add, inorder to achieve delay release, use autorelease instead of release

        if(m_sprite)m_sprite->autorelease();//add, inorder to achieve delay release, use autorelease instead of release

      }

      bool init(){

        m_sprite=Sprite::create("a.png");

        this->addChild(m_sprite);

        m_sprite->retain();//add

        m_renderTex=RenderTexture::create(w,h);

        this->addChild(m_renderTex);

        m_renderTex->retain();//add

        

        return true;

      }

      void udpate(float dt){

        m_renderTex->begin();

        m_sprite->visit();

        m_renderTex->end();  

      }

      void onExit(){

             CCLayer::onExit();

               this->unscheduleUpdate();//add, stop update as soon as possible

        }

    private:

      RenderTexture* m_renderTex;

      Sprite* m_sprite;

    };

    我不知道这两处改动是否都是必须的,由于是概率性崩溃,验证和重现比较耗时,所以在没有更清晰的分析之前暂时两处改动都保留。如此改之后目前为止还没有再发生崩溃。但这种修补显然是不自然的,不知道有没有更好的办法。

  • 相关阅读:
    设置网络
    href
    webpack学习
    那些个像素
    jquery Id选择器与document.getElementByIdy区别
    又一个很垃圾的设计
    卸载QQ,360,迅雷,搜狗
    CheckFail设计很垃圾
    js写法【2】
    require的定义看不懂【2】
  • 原文地址:https://www.cnblogs.com/wantnon/p/4403401.html
Copyright © 2020-2023  润新知