iPhoneクラスのgenerationプロパティからデバイス情報を知ることができます。
Debug.Log(iPhone.generation);
特定の機種を判別したいときには
1 2 3 4 5 |
if (iPhone.generation == iPhoneGeneration.iPhone4S) { // 画面上部の広告を表示しない myAd.DisableUpper(); } |
※判別可能なデバイスは、ドキュメントのiPhoneGenerationを参照
スクリーンサイズからデバイスを判定する方法は
Unity3D:iOSデバイスの判定
以前、アプリを開発している時、Random.Range()で取得した乱数の偏りが気になりました。
※厳密に調べたわけでないので本当に偏っているかは分かりません
今は以下の様なRandomControllerクラスを用意して乱数を取得しています。
1 2 3 4 5 6 7 8 9 10 11 |
using System; public class RandomController { static Random rnd = new System.Random(); static public int getNumber(int n) { return rnd.Next(0, n); } } |
使用方法は
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メソッドを実行しています。
1 2 3 4 5 6 7 8 9 10 |
public class CardOnStage : MonoBehaviour { LabelOwner _labelOwner; void Awake() { this._labelOwner = transform.FindChild("_LabelOwner").GetComponent<LabelOwner>(); this._labelOwner.SetLabel(true); } } |
LabelOwnerクラスのAwake()で、UILabelコンポーネントを取得しています。
SetLabelメソッド内では、Awake()で取得済みのUILabelコンポーネントのtextプロパティへ値を設定しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class LabelOwner : MonoBehaviour { UILabel _uiLabel; static string _nameDealer = "DEALER"; static string _namePlayer = "PLAYER"; void Awake() { this._uiLabel = GetComponent<UILabel>(); } public void SetLabel(bool isDealer) { if (isDealer) { this._uiLabel.text = _nameDealer; return; } this._uiLabel.text = _namePlayer; } } |
上記2つのクラスのAwake()が
1. LabelOwnerクラス
2. CardOnStageクラス
の順番に実行されていればNullReferenceExceptionは発生しません。
実行順が逆になると問題が発生します。
CardOnStageクラスのAwake()のGetComponentは問題なく実行されますが、次のSetLabelメソッドの呼び出しで問題が発生します。この時点ではLabelOwnerクラスの_uiLabel変数にはUILabelコンポーネントが設定されていません(Awakeが実行されていない)。SetLabelメソッド内でtextプロパティに値を設定しようとした時にNullReferenceExceptionが発生してしまいます。
エラーを防ぐには
CardOnStageクラスのAwake()にあったSetLabelメソッドの呼び出しをStart()へ移動すれば問題は起きません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class CardOnStage : MonoBehaviour { LabelOwner _labelOwner; void Awake() { this._labelOwner = transform.FindChild("_LabelOwner").GetComponent<LabelOwner>(); } void Start() { this._labelOwner.SetLabel(true); } } |
スクリプトの実行順を指定するか、実行順が変わった時に問題が起きないように注意してコードを書く必要があります。
現在のステートの情報はAnimatorクラスのGetCurrentAnimationStateInfo()で取得する。
取得した値(AnimationStateInfo)には、現在のステートに関する幾つかの値が含まれている。
ただし、この値からステートの名前は直接知ることは出来ない模様。
予め比較対象のステート名からハッシュを取得しておき、nameHashプロパティの値と比較することで、どのステートに居るかを知る。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
Animator _anim; int _stateCardFace, _stateJumpCard; void Awake() { this._anim = GetComponent<Animator>(); this._stateCardFace = Animator.StringToHash("Base Layer.CardFace"); this._stateJumpCard = Animator.StringToHash("Base Layer.JumpCard"); } public void JumpCard(bool start) { AnimatorStateInfo anim = this._anim.GetCurrentAnimatorStateInfo(0); if (start) { if (anim.nameHash == this._stateCardFace) { this._anim.SetTrigger("JumpStart"); } return; } if (anim.nameHash == this._stateJumpCard) { this._anim.SetTrigger("JumpStop"); } } |
7, 8行目 2つのステートのハッシュをレイヤー名とステート名から取得。
13行目 現在のステート情報を取得。
16, 22行目 現在のステートのハッシュと予め取得してあったステートのハッシュと比較。
列挙型の値から名前を得るにはToStringメソッドを使用する。
列挙型の定義
1 2 3 4 5 6 7 8 9 10 11 12 |
public enum HAND_NAME { NONE, JACKS_OR_BETTER, TWO_PAIR, THREE_OF_A_KIND, STRAIGHT, FLUSH, FULL_HOUSE, FOUR_OF_A_KIND, STRAIGHT_FLUSH, ROYAL_STRAIGHT_FLUSH, }; |
列挙型の名前を得る
1 2 3 4 5 6 |
public void Show(HAND_NAME hand) { if (hand == HAND_NAME.NONE) return; this._uiLabel.text = hand.ToString().Replace('_', ' '); } |
この例では、ToString()で文字列に変換し、区切り文字として使っていた”_”(アンダースコア)はReplace()で空白に置き換えている。