Cocos Studio2 のバグをなんとかした話
吉田です。
先日から悩んでいた Cocos Studio2 のバグをなんとかした勝利の喜びを是非両親とわかちあいたいです。
両親は技術的な事なんてまったくわからないでしょうけど。
何が起きたのか
Cocos Studio2(for MAC) で生成した csb ファイルを cocos2d-x の edge で使ったところ、
Layer を含んだ Scene を表示しようとした際に存在しないはずの AnimationTimeline の Vector がなぜか size 7 で確保され、
その中にアクセスすると Bad Access になって止まってしまいました。
調査
Cocos Studio2 の csb ファイルの正体をまず調べました。
Cocos Studio2 ではプロジェクトディレクトリの cocosstudio ディレクトリ以下に csd というファイルを作ります。この中身は xml でした。
また Cocos Studio2 で publish を行うと プロジェクトディレクトリ下の res ディレクトリに csb というファイルを生成します。この csb の正体が何なのかを cococs2d-x のソースより調べたところ flatbuffers という google 社製のオブジェクトシリアライズフォーマットであることがわかりました。
この時点で最悪 flatbuffers のバグも疑わなければいけないところですがとりあえずは cocos2d-x のほうをもっと調査しようと思いました。
調べると cocos2d-x の中に csd ファイルを csb ファイルに変換する処理がありましたので、まずはこれを使ってみて、同じ形のバイナリが吐かれるかを確かめる事にしました。
検証
コードを読んでいくと editor-support/cocostudio/FlatBuffersSerialize.h では serializeFlatBuffersWithXMLFile という処理があってこれで csd を csb に変換出来る事がわかりました。
とりあえずはこれをゲームのコード内で使ってみて csb を生成してみました。 生成した csb をバイナリエディタで見て比較してみたところまったく違うバイナリが吐かれていました。
さらに生成した csb を使ってみるとバージョン番号チェックで csb ファイルのバージョンは 2.1.0.0 だけれどデシリアライズするコードでは 2.0.8.0 のフォーマットしか受け付けないというアサーションで止まりました。
そこでバージョンチェックをコメントアウトして走らせてみたところ、期待どおりにパースされ、問題無く動きました。
これにより、 Cocos Studio 2.1beta によるシリアライズと cocos2d-x edge によるデシリアライズに差が生じているため起きた事だという事がわかりました。
対策
ここまで行くと話は簡単です。
Cocos Studio によるシリアライズは使わず cocos2d-x によるシリアライズを行えば良いことになります。
話は簡単なのですが、実装は難しいというのは世の常、ゲームのコード内で毎回生成するのも良くないので、専用のツールを作ることにしました。
作ったモノは以下のリポジトリで公開しています。
cocos2d-x をコマンドラインで使うという変わったものとなっていて、 Makefile を書くのが非常に辛かったです。
感想
edge を使うというのはいろいろと不具合を踏み倒す事ですし、踏み倒す事で踏み方のノウハウも付きます。
今回の場合 Cococs Studio2 のコードが公開されていればもう少しマシな対応が出来たかもしれませんが、今回の対処方法もまずまずではないでしょうか。
このツールを使っている限りはとりあず今回の不具合でダメになることはない事が期待できます。
このツールを作る事が出来たのも cocos2d-x 自体が OSS だったからです。
Unity 全盛な感じもしますが OSS の価値というのは素晴らしいです。
(はぁしんどかった。)