Unityで、スクリプトを組んでいるとGameObjectを取り扱うことが多いと思います。取得する方法はいろいろあるようですが、自分の中でよく使うものをまとめてみました。
概要
記事の中で取り上げる方法は以下の5つです。
- Inspectorで設定する
- 実装的にも処理的にもおそらく一番楽です。
- 状況によって実装できない場合もあります。
- GameObject.Findを使う
- SceneのGameObjectを検索してきます。他で取得が難しい時は、これが簡単です。
- ただし、処理は重い(すべてのObjectを検索するので)ので、Startで実行するなど、実行回数を減らす工夫が必要です。
- タグでの取得
- FindGameObjectsWithTagを使って、指定したタグのついたオブジェクトをすべて取得します。
- 複数のオブジェクトを取得する必要がある時、タグでまとめられるので便利です。
- タグの管理が多少、面倒ではあります。
- オブジェクトの子オブジェクト名を指定して取得する
- transform.Findで、子オブジェクトの中から指定したオブジェクト名を取得します。
- Prefabで同じようなオブジェクトが大量にできる時などに便利です。
- 子オブジェクトを一括で取得する
- GetChild(i)をアレンジして取得します。
- タグの管理が不要になります。transformで探しやすいときに使いやすいです(カードゲームの手札を検索するなど)。
GameObjectを取得する方法
Inspectorで設定する
一つ目は変数だけスクリプト側で用意して、Inspectorから設定する方法です。
やり方としては一番簡単で、検索の処理なども入らないので、やりやすいと思います。ただ、最初からシーンに設定してあるオブジェクトやプレハブしか指定ができません(やり方あるかもですが、自分は知りません)。ゲームの状況に応じて、GameObjectを取得するには他の方法を使う必要があります。
やり方
前提として、HierarchyにObject1とObject2というGameObjectを作成し、Object1にGetGameObjectというスクリプトをアタッチして、Object2のGameObjectを取得する、ということをやってみます。
- スクリプトでGameObjectの変数を用意します。
- ソースコードの中身を用意します。とりあえず、Startでオブジェクトの名前を出力します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetGameObject : MonoBehaviour
{
[SerializeField] GameObject Object;
void Start()
{
// オブジェクトに対しての処理を書く
Debug.Log(Object.name);
}
void Update()
{
}
}
- スクリプトを保存して、Unityの編集画面に行く。スクリプトをアタッチしているオブジェクトのInspectorを開き、ドラッグ&ドロップで変数にGameObjectを入れる。
- ゲームをスタートすると、処理が実行されています。(Consoleにnameが表示される)
GameObject.Findを使う
オブジェクト名を指定して、Sceneの中にあるGameObjectを取得してきます。
オブジェクト名を指定するだけなので、実装は簡単ですが、オブジェクトを全て検索するので、処理は重くなるようです。これを使う場合、Startで一度呼び出すだけにするなど、呼び出す回数は少なくする工夫をした方がよいそうです。
やり方
先ほどと同じ事例をGameObject.Findでやってみます。
- スクリプトを用意します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetGameObject : MonoBehaviour
{
GameObject Object;
void Start()
{
Object = GameObject.Find("Object2");
}
void Update()
{
// UpdateでGameObject.Findを使うと重くなるので、Startで取得したほうがよい
// Object = GameObject.Find("Object2");
Debug.Log(Object.name);
}
}
- ゲームを開始します。処理が実行されています。
タグでの取得
オブジェクトにタグを指定して、FindGameObjectsWithTagでタグ名を指定して取得します。タグのついたオブジェクトを全て取得するので、リスト型になります。
対象が複数に及ぶ時に便利です。タグの管理がやや面倒になるのと、用意できるタグ数は上限があるらしいので注意が必要です。
やり方
オブジェクトを複数取得するので、先ほどの事例にオブジェクトを増やします。Object3とObject4を増やして、Object2とObject4を取得したい場合を考えます。
- Inspectorでタグを設定します。今回はTestTagというタグを用意しました。
- スクリプトを用意します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetGameObject : MonoBehaviour
{
List<GameObject> ObjectsList;
void Start()
{
ObjectsList = new List<GameObject>();
ObjectsList.AddRange(GameObject.FindGameObjectsWithTag("TestTag"));
// foreachで各オブジェクトに処理を行う
foreach (GameObject obj in ObjectsList)
{
// 処理を書く
Debug.Log(obj.name);
}
}
}
- ゲームを開始します。TestTagのついたGameObjectに処理が行われています。
子オブジェクトの中から検索する
transform.Findを使うと、子オブジェクトから検索ができます。Prefabのように構造が一定で、複数同じ構造のオブジェクトができる時に、便利です。
transformで取得するので、GameObjectとの切り替えには注意が必要です。
やり方
今度は先ほどまでのオブジェクトの子オブジェクトにChildObjectというオブジェクトを用意して、スクリプトを実行しているオブジェクト(Object1)の子オブジェクトを取得します。
- スクリプトを用意します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetGameObject : MonoBehaviour
{
GameObject ChildObject;
void Start()
{
ChildObject = this.transform.Find("ChildObject").gameObject;
// 処理を書く
Debug.Log(ChildObject.name + "の親は" + ChildObject.transform.parent.name);
}
}
- ゲームを開始します。処理が正しく実行されています。
子オブジェクトを一括で取得する
transform.Findでは一つのオブジェクトしか取得できません。GetChild()を使って子オブジェクトを一括で取得、処理を行うことができます。
タグの管理が不要で、transformが固定されているところで処理を行うのに使いやすいです(カードゲームを作っている時にPlayerHandの子にあるカードをすべて取得する、など)。
やり方
今回は、Object1の子オブジェクトを3つに増やして、すべての子オブジェクトを取得します。
- スクリプトを用意します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetGameObject : MonoBehaviour
{
List<GameObject> ChildsList;
void Start()
{
// 子オブジェクトの数を取得
int childCount = this.transform.childCount;
for (int i = 0; i < childCount; i++)
{
Transform ChildTransform = this.transform.GetChild(i);
// 処理を書く
Debug.Log(ChildTransform.name);
}
}
}
- ゲームを開始します。処理が実行されます。
おわり
探せばもっとありそうですが、自分はここに書いたような方法で取得しています。
深く考えなければ、全部GameObject.Findでいい気もしますが、処理の重さなどを考えると、なるべく検索範囲が少なく済むような方法を選ぶとよさそうです。
コメント