Unityで特定のGameObjectをアクティブにしたい場合、SetActiveを使うがGameObject.Findで取得しようとするとnullが返ってくる。
これはGameObjectクラスのGameObjectを取得するstaticメソッド(GameObject.Find、FindWithTag)がアクティブなGameObjectしか対象にしないため。
http://docs-jp.unity3d.com/Documentation/ScriptReference/GameObject.html
アクティブでないGameObjectを取得するには以下の様な方法が考えられる。
- publicなメンバー変数にGameObjectをエディタから登録しておく。
- 親のGameObjectからTransform.Findを使う。
- 最初はアクティブにしておいてGameObject.Findで探して変数に覚えた後で非アクティブ化して必要なときに変数を参照する。
1.メンバー変数にGameObjectをエディタから登録
一番わかりやすくて、速度も良さそう。ただ大量に設定する場合に心が折れてしまう。
また複数人で編集している場合、つけ忘れたり、いつの間にか外れていたりするので自動的に設定したい。
2.親のGameObjectからTransform.Find
Transform.Findで取得する方法。この場合アクティブじゃなくても取得できる。
結果はTransformなのでgameObjectプロパティを参照する。
// parentはTargetの親のGameObject GameObject g = parent.transform.Find("Target").gameObject;
3.最初はアクティブにしておく
Awakeで探して覚えておいて、非アクティブにする方法。
全部アクティブにしてしまうとエディタのシーン上での見た目がアレ。
private GameObject target; void Awake() { target = GameObjct.Find("Target"); target.SetActive(false); }
ついででGameObjectを探すときの速度を計測してみた。
GameObject – Targetという風にHierarchyにGameObjectを配置。
void Start () { float start = Time.realtimeSinceStartup; for (int i = 0; i < 10000; i++) { // Targetという名前のGameObjectを探す GameObject g = GameObject.Find("Target"); } start = Time.realtimeSinceStartup - start; Debug.Log(start); }
- GameObject.Find : 0.002311897
- GameObject.FindWithTag : 0.003102157
- Transform.Find : 0.003460165
Transform.Findが思いのほか遅かった。見つけた後にgameObjectプロパティにアクセスしているせいかもしれない。
コメントを残す