在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;

};

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

cocos2dx 3.3 场景切出时RenderTexture crash的更多相关文章

  1. 微信小程序自动化jest模拟场景/切出/切入

    await miniProgram.evaluate(() => getApp().clickBanner({ path: "pages/game/home/home", q ...

  2. 关于png、jpg、gif切图时的使用感悟

    关于png.jpg.gif切图时的使用感悟 曾经切图时都是一股脑所有图全切成jpg格式,最近突然心血来潮简单的研究了下其他图片格式的具体属性,才突然发现走了不少弯路,并没有做到使图片用最小体积展现出最 ...

  3. Android应用第一次安装成功点击“打开”后Home键切出应用后再点击桌面图标返回导致应用重启问题

    最近项目中遇到一个问题,用户第一次安装应用在系统的安装器安装完成界面有“完成”和“打开”两个按钮. 当用户点击“打开”按钮进入用户注册页面进行手机号验证码发送和验证码输入等操作界面,若此时用户点击Ho ...

  4. cocos2dx中的场景和使用方法

    1.一个游戏中有且只有一个导演,但是至少有一个场景 2.场景是游戏元素节点数的根节点,也可以理解为该场景下的渲染树的根节点 3.场景是一个容器,包含了该场景下的所有游戏元素,比如层,精灵 4.场景是导 ...

  5. Android 软键盘弹出时把原来布局顶上去的解决方法

    键盘弹出时,会将布局底部的导航条顶上去. 解决办法: 在mainfest.xml中,在和导航栏相关的activity中加: <activity            android:name=& ...

  6. 当SD卡拔出时,返回首页,栈中的activity都要清除,只留下首页的activity

    目标:当SD卡拔出时,返回首页,栈中的activity都要清楚,只留下首页的activity 我在清单中注册了一个静态广播: <receiver android:name="com.p ...

  7. svn 切出指定版本、更改版本名称、删除分支

    1,切出指定版本 svn copy svn://192.168.1.52/help/branches/help_forShop_140307 -r 170 svn://192.168.1.52/hel ...

  8. 切服务器时请注意robots.txt文件

    最近两天切服务器时又出现测试机器忘记改robots.txt文件的情况,以后就用个二级域名做测试,测试的机器也不对robots.txt作限制.

  9. 学习笔记:只有一套app设计稿(5s尺寸)切出4和4s尺寸以及安卓系统主流尺寸的图

    如何在只有一套app设计稿(5s尺寸)切出4和4s尺寸以及安卓系统主流尺寸的图 转自:http://www.zhihu.com/question/23255417   版权归原作者所有 目前ios手机 ...

随机推荐

  1. Andriod中的依赖注入

    Web后端开发者应该对依赖注入都比较熟悉,至于Android又是如何进行依赖注入的呢?在这篇文章中,让我们一起通过一个例子了解一下在Android中进行依赖注入的好处. AndroidAnnotati ...

  2. 如何用7-zip创建自解压文件,7Z软件如何使用

    1 要创建自解压文件,一般都是双击直接解压到C盘的Program Files文件夹里面,或许还需要在桌面创建一个快捷方式之类的.但是一般的绿色软件除了复制到Program Files还需要运行一下绿化 ...

  3. git多仓库管理

    使用git建立多仓库管理 以下操作为命令行下操作 一:先创建服务器端口,总仓库和子仓库: ssh git@192.168.1.110        连接git服务器 输入密码 mkdir iOSPro ...

  4. Tomcat环境的搭建(web基础学习笔记一)

    一.下载和安装Tomcat服务器 下载Tomcat安装程序包:http://tomcat.apache.org/ 点击[Download]跳转到如下图所示的下载页面 二.点击左侧要下载的版本,选择To ...

  5. 算法笔记_108:第四届蓝桥杯软件类省赛真题(JAVA软件开发本科A组)试题解答

     目录 1 世纪末的星期 2 振兴中华 3 梅森素数 4 颠倒的价牌 5 三部排序 6 逆波兰表达式 7 错误票据 8 带分数 9 剪格子 10 大臣的旅费 前言:以下试题解答代码部分仅供参考,若有不 ...

  6. Linux下Tar压缩使用

    具体的可以在linux环境下 用tar --help查看详细说明格式:tar [option] file -c create create a new archive -x extract extra ...

  7. eclipse手动指定启动的jdk版本

    在eclipse.ini中添加 -vm D:/wwjDocument/JDK6/jre/bin/client/jvm.dll -vmargs -Dosgi.requiredJavaVersion=1. ...

  8. mysql优化利器之explain

    一.语法 {EXPLAIN | DESCRIBE | DESC} tbl_name [col_name | wild] {EXPLAIN | DESCRIBE | DESC} [explain_typ ...

  9. ASP.NET#命名空间"System.Data"中不存在类型或命名空间名称"Linq"(是否缺少程序集引用?)

    添加完.dbml(LINQ to SQL类文件)文件后,双击.designer.cs源文件时,发现编译器提示:命名空间"System.Data"中不存在类型或命名空间名称" ...

  10. Centos5 下redmine的安装及配置

    Redmine: 这是基于ROR框架开发的一套跨平台项目管理系统,是项目管理系统的后起之秀,据说是源于Basecamp的ror版而来,支持多种数据库,除了和 DotProject的功能大致相当外,还有 ...