私が以前にUnityで開発したゲームアプリが、最近ちょっとした表示不具合に見舞われたためバグFIXを行ったのですが、いろいろと予想外の壁があり時間を取れれることになりました。
結果的に、Web上でいろいろな情報を集め、さらには気の遠くなるような試行錯誤を繰り返した後、ようやく解決できたのですが、たぶん、他にもはまる方がいる可能性があると思いレポートさせていただきます。
●iOS8.2以降でテキストが表示されない不具合
まず、私のアプリですが以下の簡単なスポーツゲームです。
http://app-liv.jp/922419656/
最近見舞われたというバグの箇所は、スクリーン上部中央の赤枠部分。
ここには本来、ゲームのレベルとそのレベルをクリアするのに必要なポイント数がテキスト表示されていました。
それがどういうわけかiOS8.2以降、表示されなくなっていたのです。
他の開発者の方のブログなどでいろいろと調べたところ、Unityで作成したアプリのテキスト部分がiOS8.2以降はどういうわけか表示されないという不具合が他でも見られるとのこと。
http://qiita.com/JunSuzukiJapan/items/c9265017956e901b9278
解消方法としては、
「Unity4.6.1以降のバージョンを使ってビルドしなおすと直る。」
ということなので、これは簡単だ、とばかりにやってみました。
Unityでビルドし、Xcodeへ。
iPhone6でテストしたところ嘘のように問題なく表示されました。
読んだ記事の通りで本当に簡単だ、と安心しました。
ところが・・・いざItunesConnectにアップしようとしたところ、はねられてしまいました。
●iOSアプリは64bit対応が必須になっていた
エラーメッセージを読んだところ、どうやら
「iOSアプリは64bit対応してないと申請できません」
と書いてあるよう。
そういえば、そんな話があった、とようやく思い出しました。
2015年2月以降、 iOS アプリはすべて、64-bit サポートを含んでいないと受け付けなくなる、という予告があったため、そうなると面倒くさそうだとばかり私は上記アプリを慌てて公開していたのでした。
しかし、当然ながらUnityはそれに対する対応もしてくれているだろう、と調べたところ、「IL2CPP」なる方法でC#やJSスクリプトを C++ へ変換する仕組みを導入したとのこと。
具体的には以下記事にあるように「PlayerSetting」>「Other Settings」内で「IL2CPP」を選択するなどごく簡単な作業で良いらしい。
http://qiita.com/dsgarage/items/3f1483b19ac0feab4473
なるほど、これも簡単で良かった。
とほっとして再ビルドをしてみました。
Xcodeで開いてiPhoneでテスト♪
しかし、途中でフリーズしてしまう。。。
Unityではエラーが出ていなかったのに、Xcodeでは
「Thread 1: EXC_BAD_ACCESS(code=1,address=0x2c)」
という意味不明なエラー表示。
うん、これはなんだ???
●エラーの意味を探して四苦八苦
そもそも意味が分からなかったのは、これまではまったく問題なくAppStoreで公開していたのに、しかも、Unity内ではスイスイ動いているのに、なぜXcodeでエラーになるの?
ということでした。
32bitから64bitにしたことで、一体何が変わったんだろう?
と考えても考えても分かりません。
Web上で上記エラーログで検索してみても、よく分からない。
書く人によって言うことが全然違うのです。
スクリプトの構造から見直すべきという人もいれば、NullExceptionになっている箇所を探すべきという人もいる。
日本語での情報がとにかく少ないので海外のフォーラムを懸命に読んで見るのですがさっぱり分からない。
ここでいったんあきらめようかなと思いました。
テキストが表示されないだけのバグなので、まあ良いかと。
しかし、次の日になっても気持ちが悪くて仕方ないので、ついにローラーでバグの箇所を探すことにしました。
怪しげな箇所を一つ一つ外していき、その都度ビルドしXcodeでテストしてみる。
uGUIが出る前に作ったアプリなので、OnGUI()が怪しいかな、とその箇所をすべて消してみたり、C#の記述方法がまずいのかなといろいろと書き直してみたり、ボールがバウンドするときにフリーズしているので、Terrainがまずいのかと思いPlaneに変えてみたり、ボールのメッシュが何かまずいのかなと思い、標準のSphereに変えてみたり、、、
とここでフリーズが起こらなくなりました。
ボールがまずいのか・・・
しかし、それほど重いメッシュやテクスチャーでもなく、何が悪いのか分からない。
とりあえず、動けば良いとばかりにSphereを使い、元々のボールにくっつけていたScriptや効果音のデータをくっつけてビルドしてみる。
フリーズする・・・
ん? ということは、メッシュではないのか。
ということで、ボールにくっつけていたスクリプトを探ってみることに。。。
●原因は、「OnCollisionEnter」
しかし、スクリプトといっても、地面にボールが当たった時に効果音を鳴らす、というだけのシンプルなものです。
using UnityEngine;
using System.Collections;
public class BallSe : MonoBehaviour {
void OnCollisionEnter(){
audio.Play ();
}
}
たったこれだけ
これの一体何がまずいのか・・・
とりあえず、OnCollisionEnter()メソッドを再度公式サイトで調べ直してみます。
すると、
void OnCollisionEnter(Collision collision)
と書いてある。
ああ、そういえば引数を忘れてた。
赤字部分の、接触したコリジョンの情報が入る変数部分です。
え、もしかしてこれ?
この部分は特に引数を指定しなくてもこれまでは動いていました。
私の参考にしているサイトや、あるいはたぶん書籍なので、ここが空欄になっていたものをならってこのように描いていたはずです。
とりあえず、「Collision collision」とそのまんまの引数を指定してビルド・・・
動いた・・・
え、これだけ?
みたいな、徒労感と失笑が湧いてきました。
IL2CPP使用だと、この引数の書き漏れが許されないようです。
ということで、同様のエラーの際にはOnCollisionEnter()を疑ってみましょう、という結論でした。