Unityでアプリを作っていると、Unityエディタで動いたからOKって思っちゃうんですよね。
iOSビルドして実機確認すべきなんですが、スキップしてそのままAppStoreに申請しちゃったり。
でもね、Unityエディタで動いて、実機iPhoneで動かないってことがこの前あったんですよ。
具体的にはiPhoneの画面をタップしても反応しない。
パズルゲームで、ボールをタップすれば光ようにしたんですがタップしても光らない。
Unityエディタなら完璧に動いているのに。
なんなら、UnityRemote5使ってiPhoneで動かしてもちゃんと動作してましたよ。
なんじゃこりゃ。
まー、まず疑うのは入力系ですよね。
Inputクラスの`GetMouseButtonDown`が悪さをしているのではないかと調べてみる訳です。
結論から言うと、この子は犯人ではありませんでした。
このメソッドはiPhone/Androidでもちゃんと動作します。
他のアプリで普通に使って動いているし。
Mouseって書かれているけどタップでも大丈夫です。
ちなみに、iPhoneでの犯人探しでも、Debug.Log
を使うと良いですよ。
Xcodeのコンソールにログが出力されます。
これ知らなくて実機動作確認めっちゃ苦労してました。
次に目をつけたのが、`ScreenPointToRay`。
こいつは、スクリーン座標をワールド座標に変換して、カメラの座標から進む光線を求めるのです。
この子も問題なし。
で、最後に残ったのが、`Physics.RaycastAll`さん。
あなたが犯人でした。
これは光線がオブジェクトと当たったかどうかを調べるために使われます。
光線が当たった全てのオブジェクト、つまりRaycastHit
の配列を返してくれます。
私のコードでは、配列の最初の値を取り出して使っていたのですが、この処理がどうもマズかったらしい。
Unityエディタで実行した時の配列の中身の順番と、iPhoneで動かした時の配列の中身の順番が違っていたのです。
Unityエディタ:(A,B)からAを取り出して処理。正常。
iPhone実機:(B,A)からBを取り出して処理。バグ発生。
ってことでした。
解決策としては、タップ時に必ずAを取得できるように、Aにレイヤーを設定して`Physics.Raycast`を使うようにしたら解決しました。
(昔書いた記事が役に立ちました。【Unity】Rayを特定のLayerに当てる方法)
この手のバグは見つけづらいですよね。
同じ問題で困っている方がいれば参考になれば幸いです。
おわり。