はじめに
この記事ではオブジェクトの参照方法を紹介します。
— YouTubeなら8分18秒で学べます ―
準備
Hierarchy上で右クリックして、
「Create Empty」より空オブジェクトを生成し、
「Parent」という名前に変更しました。
次に、Parentの子オブジェクトにCubeを設置してください。
Cubeを子オブジェクトにするには、
CubeをドラッグしてParentの上でドロップしてください。
今回は「Test.cs」スクリプトにコードを記入し、
GameObjectにアタッチしてCubeを取得していきます。
GameObject.Findを使った参照方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { // Use this for initialization void Start() { GameObject g = GameObject.Find("Parent/Cube"); Debug.Log("Name:" + g.name); } // Update is called once per frame void Update() { } } |
1 2 3 |
実行結果 Name:Cube |
Hierarchy上のオブジェクトを取得するときは、
1 |
GameObject.Find("オブジェクト名"); |
のように記入します。
今回のように子オブジェクトを取得するときは、
1 |
GameObject.Find(親/子"); |
のようにスラッシュで区切って下の階層に降りてください。
ただし、子オブジェクトが非アクティブの場合は
この方法ではエラー(NullReferenceException)になります。
SetActive = false 等で非アクティブにした場合は
以下のコードで取得できます。
1 |
GameObject g = GameObject.Find("Parent").transform.Find("Cube").gameObject; |
上記のように、一度アクティブなオブジェクトを取得し、
transform.Find(“オブジェクト名”)と記入すると、
非アクティブなオブジェクトも取得できます。
これが最も基本的な参照方法ですが、
GameObject.Findは比較的処理が重く、
多用は推奨されておりません。
そこで、以下のように、
Hierarchyから直接参照するか、
Tagを使って参照する方法があります。
Hierarchyから直接参照する方法
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 26 27 28 29 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { public GameObject g; [SerializeField] private GameObject k; // Use this for initialization void Start() { Debug.Log("Name:" + g.name); Debug.Log("Name:" + k.name); } // Update is called once per frame void Update() { } } |
1 2 3 4 5 |
実行結果 Name:Cube Name:Cube |
処理の遅い「GameObject.Find」を使わずに参照するには、
1 |
public GameObject g; |
のようにpublic変数で宣言してください。
スクリプトをアタッチしたオブジェクトをクリックすると、
public変数はInspectorに表示されていると思います。
その変数に参照したいオブジェクトを
ドラッグ&ドロップしてください。
これで、Findを使わずに参照できます。
これはシーンをロードしたときから取得しているので、
比較的負荷が軽いみたいです。
注意点として、private変数はInspectorには表示されません。
そこで、
1 |
[SerializeField] private GameObject k; |
のように[SerializeField]を頭につけてください。
これでInspector上に表示されます。
private や [SerializeField] について知りたい方はこちらの記事もおすすめです。
グローバル変数とローカル変数の違いと「Serializefirld」でインスペクター上に変数を表示させる方法
Tagを使った参照方法「FindWithTag」
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { // Use this for initialization void Start() { GameObject g = GameObject.FindWithTag("Cube"); Debug.Log("Name:" + g.name); } // Update is called once per frame void Update() { } } |
1 2 3 |
実行結果 Name:Cube |
Tagを使ってFindする場合は、
まず、オブジェクトにTagを付ける必要があります。
CubeのInspectorのTagをクリックし、「Add Tag」をクリック。
Tagsの右下にある+ボタンをクリックし、
New Tag Name に Cubeと入力してSaveしてください。
Tag名は何でも構いません。
これでCube Tagが現れるので選択します。
これで、以下のコードを入力すると、
Tagを使ったFindが可能になります。
1 |
GameObject g = GameObject.FindWithTag("Cube"); |
ちなみに、Tagを使えば直接参照できるので、
親子の関係を考慮する必要が無くなります。
しかも、通常のFindと比較して低負荷で取得できます。
各種Findで速度テストをした記事があるので、
興味がある方はどうぞ。
— コガネブログ ―
【Unity】GameObject.Find 系関数の処理速度の検証結果
しかしながら、このFindには1つ注意点があります。
それは、Cube Tagが複数のオブジェクトについているとき、
上記のコードではどのオブジェクトを取得するか分からない点です。
もし、似たようなオブジェクトの中から
特定の1つを指定したい場合は、
TagをCube1、Cube2のように分けるか、
普通のFindを使用してください。
Tagが付いた複数のオブジェクトを同時に取得する方法
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 26 27 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { // Use this for initialization void Start() { GameObject[] g = GameObject.FindGameObjectsWithTag("Cube"); Debug.Log("Name:" + g[0].name); Debug.Log("Name:" + g[1].name); Debug.Log("Name:" + g[2].name); } // Update is called once per frame void Update() { } } |
1 2 3 4 5 6 7 |
実行結果(今回の場合) Name : Cube1 Name : Cube2 Name : Cube |
HierarchにCube1とCube2を追加し、
両方ともTagにCubeを設定します。
Cubeタグが付いているオブジェクトを全て取得したい場合、
1 |
GameObject[] g = GameObject.FindGameObjectsWithTag("Cube"); |
のように記入します。
配列データとして取得しているので、
使用する際は以下のようになります。
1 2 3 |
Debug.Log("Name:" + g[0].name); Debug.Log("Name:" + g[1].name); Debug.Log("Name:" + g[2].name); |
ただし、これもどういう順番で配列に格納されるかは分からないので、
上記のように番号を指定して使用するのは難しいです。
これはforeachを使って、
全てのオブジェクトを消したり、
移動させるといった使い方がほとんどです。
例えば、爆風に巻き込まれて
Cubeタグが付いているオブジェクトは全て消す、
といった場合は以下のように消します。
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 26 27 28 29 |
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Test : MonoBehaviour { // Use this for initialization void Start() { GameObject[] g = GameObject.FindGameObjectsWithTag("Cube"); foreach (var obj in g) { Destroy(obj); } } // Update is called once per frame void Update() { } } |