夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【cocos2d-x】シーン切り替え時のFatal signal 11 (SIGSEGV)クラッシュはノード解放で解消?

ゲームオーバーからタイトル画面にシーン切り替えするときクラッシュするという問題に悩まされました。

アドレスやスレッドの番号は毎回違いますが、このFatal signal 11 (SIGSEGV)というエラーです。

Fatal signal 11 (SIGSEGV) at 0x7879469c (code=1), thread 5423 (Thread-29348)

iOSでは発生せず、Androidのみで発生する状況だったので、デバッグに非常に苦労しました。(Eclipseでのデバッグ方法を知らないので・・・)

特定の状況だとほぼ100%クラッシュすることを突き止めたので、その辺りを重点的にチェックします。
具体的には、3面のボス、ヌタウナギとの対戦中にゲームオーバーになり、コンティニューせずにタイトル画面に戻った瞬間かなりの高確率でクラッシュが発生するという状況。
このシーンです。
f:id:takujidev:20150327214517j:plain
別の面のボスのサメとの対戦ではクラッシュしないのでウナギのプログラムに何か問題があるのかと思いましたが、どうやらそうではなく、負荷が重い状態からのシーンチェンジに問題があるようです。
ちなみに、このシーンでのGL Vertsは1260になっています。

そこで、シーン切り替えの直前に画面上のスプライトを全て親ノードから外すようにしてみました。
TravelShooting JPはZ座標に応じてスプライトのz値を毎フレーム変更して3Dの重ね合わせをしている都合上、全てのキャラクターをBatchNodeというノードにAddChildしています。(名前はBatchNodeですがバッチ処理はしていません。)そして、キャラクターの影の濃さが一定になるよう、ShadowBatchNodeというRenderTextureに全ての影スプライトをAddChildしています。
したがいまして、これらの2つの親ノードからremoveAllChildrenWithCleanup(true)で子ノードを外し、その後replaceSceneするようにしました。

    BatchNode::getInstance()->removeAllChildrenWithCleanup(true);
    ShadowBatchNode::getInstance()->removeAllChildrenWithCleanup(true);
    auto transition = TransitionSlideInR::create(TRANSITION_TIME, TitleScene::createScene());
    Director::getInstance()->replaceScene(transition);

早速試してみたところ、あれほど頻繁に発生していたクラッシュが全く発生しなくなりました!
https://itunes.apple.com/jp/app/travelshooting-jp-toraberushutingu/id917570972?mt=8&uo=4&at=10laCt
https://itunes.apple.com/jp/app/beecluster-wu-liaono-zongsukurorushutingugemu/id663801586?mt=8&uo=4&at=10laCt