GameObjectには何が付いている? GetComponentsでComponent一覧を表示してみよう【Unity】

広告

前回の記事「new GameObject()から作ってみよう ― UnityのComponentはどう組み合わさるのか」では、GameObjectにComponentを追加して、落下する四角形を作りました。

今回は、そのGameObjectに何が付いているのかを、C#から調べてみます。

Inspectorで見ていたComponentの一覧を、Consoleにも表示してみましょう。

1. Componentを「付ける」から「調べる」へ

前回は、次のようにComponentを追加しました。

obj.AddComponent<BoxCollider2D>();
obj.AddComponent<Rigidbody2D>();

AddComponentは、GameObjectにComponentを追加するメソッドです。

追加したあとで「Rigidbody2Dは付いているかな?」と調べるときは、GetComponentを使います。

Rigidbody2D rb = obj.GetComponent<Rigidbody2D>();

これは、objに付いているRigidbody2Dへの参照を取得するコードです。新しいRigidbody2Dを追加する処理ではありません。

取得した結果は、次のように確認できます。

Rigidbody2D rb = obj.GetComponent<Rigidbody2D>();

if (rb != null)
{
    Debug.Log("Rigidbody2Dが付いています", obj);
}
else
{
    Debug.Log("Rigidbody2Dは付いていません", obj);
}

指定した種類のComponentがなければ、結果はnullになります。Unity公式:GetComponent

なお、前回のようにAddComponentの戻り値を変数に入れれば、追加したComponentをそのまま使えます。追加直後に必ずGetComponentで取り直す必要はありません。

2. 付いているComponentを全部取得する

種類を指定して1つ取得するのがGetComponentです。

一方、Componentの一覧を調べたいときは、次のように書きます。

Component[] components = obj.GetComponents<Component>();

GetComponents<T>()は、指定した型に該当するComponentをまとめて取得します。

ここでは、Componentの共通の基本型であるComponentを指定しているため、TransformやSpriteRendererなどをまとめて取得できます。Unity公式:GetComponents

Component[]の[]は配列を表します。取得したComponentへの参照が、配列に入ります。

3. foreachで種類の名前を表示する

取得した配列から、Componentを1つずつ取り出します。

foreach (Component component in components)
{
    if (component == null)
    {
        Debug.LogWarning("読み込めないComponentがあります", obj);
        continue;
    }

    Debug.Log(component.GetType().Name, obj);
}

foreachは、「componentsの中身を1つずつ取り出し、componentという変数で使う」と読めます。

表示しているのは、次の部分です。

component.GetType().Name
  • GetType():そのComponentの実際の型を取得する
  • .Name:その型の名前を取得する

たとえば、実際のComponentがSpriteRendererなら、SpriteRendererと表示されます。

今回は「Componentの種類の名前を表示する書き方」として覚えれば十分です。

nullの確認は、スクリプトを読み込めないComponentが含まれていた場合に、表示処理が止まるのを防ぐためです。

4. 前回作ったGameObjectを調べてみよう

前回のObjectMakerのStart()で、Componentを追加した処理のあとに、一覧表示の処理を追記します。

同じStart()の中で、追加を終えてから調べるのがポイントです。

void Start()
{
    GameObject obj = new GameObject("FallingObject");

    SpriteRenderer spriteRenderer = obj.AddComponent<SpriteRenderer>();
    spriteRenderer.sprite = boxSprite;

    obj.AddComponent<BoxCollider2D>();
    obj.AddComponent<Rigidbody2D>();
    obj.transform.position = new Vector3(0, 3, 0);

    // ここからが今回追加する処理
    Component[] components = obj.GetComponents<Component>();

    foreach (Component component in components)
    {
        if (component == null)
        {
            Debug.LogWarning("読み込めないComponentがあります", obj);
            continue;
        }

        Debug.Log(component.GetType().Name, obj);
    }
}

前回のusing UnityEngine;、ObjectMakerクラス、boxSpriteフィールドはそのまま使います。

実行すると、Consoleに次のような種類の名前が表示されます。

Transform
SpriteRenderer
BoxCollider2D
Rigidbody2D

ここでは、表示順よりも、付いている種類がそろっていることを確認しましょう。

Play中にHierarchyのFallingObjectを選択し、InspectorのComponentと見比べてください。

Inspectorで確認していた構成を、コードからも調べられたことが分かります。

なお、ObjectMakerが付いているGameObjectと、生成したFallingObjectは別のGameObjectです。今回はobjに対して調べているため、生成した側のComponentが表示されます。

5. 任意のGameObjectを指定して調べる

次は、シーンにあらかじめ置いたGameObjectを調べてみましょう。

ComponentListDisplay.csを作り、次のコードを書きます。

using UnityEngine;

public class ComponentListDisplay : MonoBehaviour
{
    [SerializeField]
    private GameObject target;

    void Start()
    {
        if (target == null)
        {
            Debug.LogWarning("TargetにGameObjectを設定してください", this);
            return;
        }

        Component[] components = target.GetComponents<Component>();

        foreach (Component component in components)
        {
            if (component == null)
            {
                Debug.LogWarning("読み込めないComponentがあります", target);
                continue;
            }

            Debug.Log(component.GetType().Name, target);
        }
    }
}

設定手順は次のとおりです。

  1. 空のGameObjectを作り、ComponentCheckerと名前を付けます。
  2. ComponentListDisplayを付けます。
  3. InspectorのTarget欄に、調べたいGameObjectをHierarchyからドラッグします。
  4. PlayしてConsoleを確認します。

この例では、Play前にシーンに置いてあるGameObjectを指定してください。前回のように実行中に生成するものは、生成したコードの中で調べると分かりやすくなります。

6. gameObjectとtargetの違い

次の2つは、調べる相手が異なります。

gameObject.GetComponents<Component>();

これは、このスクリプトが付いているGameObjectを調べます。

target.GetComponents<Component>();

これは、Target欄に指定したGameObjectを調べます。

TargetにComponentChecker自身を指定すれば、Transformに加えて、今回作ったComponentListDisplayも一覧に表示されます。

自分で作って付けたスクリプトも、Componentの1つです。

7. 3つのメソッドを整理する

書き方何をするか
AddComponent<Rigidbody2D>()Rigidbody2Dを追加する
GetComponent<Rigidbody2D>()付いているRigidbody2Dを1つ取得する
GetComponents<Rigidbody2D>()付いているRigidbody2Dをすべて取得する
GetComponents<Component>()付いているComponentを種類を問わず取得する

GetComponentsは、指定したGameObject自身を調べます。子GameObjectに付いているComponentまで含めて調べる方法は、次の学習に回しましょう。

8. 確認してみよう

Targetに指定したGameObjectへ、InspectorからAudioSourceを追加して、もう一度Playしてください。

ConsoleにAudioSourceが増えたでしょうか。

一覧表示のコードを書き換えなくても、調べるGameObjectの構成が変われば、取得する一覧も変わります。

今回の学習で、Componentを「付ける」だけでなく、「何が付いているか調べる」こともできるようになりました。

訪問数 8 回, 今日の訪問数 8回

広告

C#

Posted by hidepon