devlog [naru design]

プログラミングやテクニカルな内容の覚え書き。

iPhoneクラスのgenerationプロパティからデバイス情報を知ることができます。

Debug.Log(iPhone.generation);

特定の機種を判別したいときには

※判別可能なデバイスは、ドキュメントのiPhoneGenerationを参照

スクリーンサイズからデバイスを判定する方法は
Unity3D:iOSデバイスの判定

ほとんど触っていなかった Shuriken でクラッカー風のパーティクルを作ってみました。

設定は以下の様な感じ。

スクリーンショット 2014-12-11 16.03.38

以前、アプリを開発している時、Random.Range()で取得した乱数の偏りが気になりました。
※厳密に調べたわけでないので本当に偏っているかは分かりません

今は以下の様なRandomControllerクラスを用意して乱数を取得しています。

使用方法は

int n = RandomController.getNumber(128);

で、0以上128未満のランダムな数を取得します。

Random.Range()よりはバラけている感じがします(自分調べ)。

モバイル向けのアプリを開発している時も、ついついOnMouseXXX()を使ってしまいます。
実は公式のドキュメントにはOnMouseXXX()はiOSやAndoridではサポート外と書かれています。

Features currently not supported by Unity iOS

http://docs.unity3d.com/Manual/iphone-unsupported.html

Scripting

– OnMouseDown, OnMouseEnter, OnMouseOver, OnMouseExit, OnMouseDown, OnMouseUp, OnMouseDrag events are not supported.

Features currently not supported by Unity Android

http://docs.unity3d.com/Manual/android-unsupported.html

Scripting

– OnMouseEnter, OnMouseOver, OnMouseExit, OnMouseDown, OnMouseUp, and OnMouseDrag events are not supported on Android.

問題なく動いている間は良いけど、動かなくなった時に「サポート外」と書かれてるので文句も言えません。
潜在的なバグを抱えることにもつながるので、OnMouseXXX()を使わないでタッチデバイス向けのコードを書いた方が良いかな…。

Unity4.5.5

NullReferenceException: Object reference not set to an instance of an object

オブジェクトがセットされていない状態(nullな状態)で、メソッドを実行したりプロパティにアクセスした時に発生するエラーです。

自分の場合は、Awake()やStart()の中身に原因があることが多いです。厄介なことに、エディターで実行している時には発生せずにXcodeプロジェクトとしてビルド&実行した後で発生することがあります。おそらく、自分でスクリプトの実行順を指定しない限り、MonoBehaviourの同じメソッドの実行順は確定していないんだと思います。

エラーが発生するケースの例

CardOnStageクラスのAwake()で、子オブジェクトにアタッチされたLabelOwnerコンポーネントを取得し、続けてSetLabelメソッドを実行しています。

LabelOwnerクラスのAwake()で、UILabelコンポーネントを取得しています。
SetLabelメソッド内では、Awake()で取得済みのUILabelコンポーネントのtextプロパティへ値を設定しています。

上記2つのクラスのAwake()が
 1. LabelOwnerクラス
 2. CardOnStageクラス
の順番に実行されていればNullReferenceExceptionは発生しません。

実行順が逆になると問題が発生します。

CardOnStageクラスのAwake()のGetComponentは問題なく実行されますが、次のSetLabelメソッドの呼び出しで問題が発生します。この時点ではLabelOwnerクラスの_uiLabel変数にはUILabelコンポーネントが設定されていません(Awakeが実行されていない)。SetLabelメソッド内でtextプロパティに値を設定しようとした時にNullReferenceExceptionが発生してしまいます。

エラーを防ぐには

CardOnStageクラスのAwake()にあったSetLabelメソッドの呼び出しをStart()へ移動すれば問題は起きません。

スクリプトの実行順を指定するか、実行順が変わった時に問題が起きないように注意してコードを書く必要があります。

現在のステートの情報はAnimatorクラスのGetCurrentAnimationStateInfo()で取得する。
取得した値(AnimationStateInfo)には、現在のステートに関する幾つかの値が含まれている。
ただし、この値からステートの名前は直接知ることは出来ない模様。

ss_2014-12-02

予め比較対象のステート名からハッシュを取得しておき、nameHashプロパティの値と比較することで、どのステートに居るかを知る。

7, 8行目 2つのステートのハッシュをレイヤー名とステート名から取得。
13行目 現在のステート情報を取得。
16, 22行目 現在のステートのハッシュと予め取得してあったステートのハッシュと比較。

列挙型の値から名前を得るにはToStringメソッドを使用する。

列挙型の定義

列挙型の名前を得る

この例では、ToString()で文字列に変換し、区切り文字として使っていた”_”(アンダースコア)はReplace()で空白に置き換えている。

5次元配列をクラス変数として作成した所、Unity上では問題なく動くのにiPhone実機でエラーが発生。

クラス変数として5次元配列のデータを初期化した。

Unity上では問題なく動作したが、iOS向けにビルドしてXcodeから実機で動かすとエラーが発生。

ExecutionEngineException: Attempting to JIT compile method …

5次元配列の値を参照しているところで上記のようなエラーが発生し動作が停止した。

Googleで検索したところ、UnityAnswersに気になる投稿を2つ発見。

“ExecutionEngineException: Attempting to JIT compile method” when Marshal.PtrToStructure function operating on iphone

http://answers.unity3d.com/questions/250803/executionengineexception-attempting-to-jit-compile.html

Why doesn’t Unity iPhone support 4D arrays?

http://answers.unity3d.com/questions/297051/why-doesnt-unity-iphone-support-4d-arrays.html

多次元配列を使うことに問題がありそうなので、配列のインデックスをフラット化して2次元配列に変換。

iPhone実機でも問題なく動作すするようになりました。

根本的な原因は分かりませんが、多次元配列は3次元程度までにしておいたほうが良いのかも…