zoukankan      html  css  js  c++  java
  • 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;

    };

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

  • 相关阅读:
    【.Net--资料】
    【系统Configmachine.config与自己的应用程序的App.config/Web.Config配置节点重复】解决方法
    【AutoMapper】实体类间自动实现映射关系,及其转换。
    【EntityFramwork--处理数据并发问题】
    【IOC--Common Service Locator】不依赖于某个具体的IoC
    Android学习——碎片Fragment的使用
    Android学习——利用RecyclerView编写聊天界面
    Android学习——控件ListView的使用
    Android学习——LinearLayout布局实现居中、左对齐、右对齐
    Android学习——Button填充颜色及实现圆角
  • 原文地址:https://www.cnblogs.com/wantnon/p/4403401.html
Copyright © 2011-2022 走看看