Version: Unity 6.0 (6000.0)
言語 : 日本語
ゲームオブジェクトの基礎
Transform

ゲームオブジェクト

Switch to Scripting

Unity の GameObject クラスは、シーンに存在するあらゆるものを表現するために使用されます。ゲームオブジェクトは、Unity のシーンを構成するブロックであり、ゲームオブジェクトの見た目や機能を決定する機能コンポーネントのコンテナとして機能します。

GameObject クラスは、コード内でゲームオブジェクトを操作するためのメソッドのコレクションを提供します。これには、ゲームオブジェクト間の検索、接続、メッセージの送信、ゲームオブジェクトにアタッチされたコンポーネントの追加や削除、シーン内の状態に関連する値の設定などを行うためのメソッドがあります。

GameObject クラスのすべてのメンバーの完全なリファレンスについては、ゲームオブジェクトのスクリプトリファレンスを参照してください。

シーンでのゲームオブジェクトの使用と Unity エディターでの階層については、ゲームオブジェクトの概要を参照してください。

シーン状態のプロパティ

すべてのゲームオブジェクトには、Inspector の上部にシーン内でのゲームオブジェクトの状態を示す一式のコントロールがあり、これらはゲームオブジェクトのスクリプティング API で制御できます。

Inspector に表示される一般的なゲームオブジェクト。ここでは、ディレクショナルライトを使用しています。シーン状態のプロパティは赤いアウトラインで示されています。
Inspector に表示される一般的なゲームオブジェクト。ここでは、ディレクショナルライトを使用しています。シーン状態のプロパティは赤いアウトラインで示されています。

アクティブ状態

ゲームオブジェクトのアクティブ状態
ゲームオブジェクトのアクティブ状態

ゲームオブジェクトはデフォルトではアクティブですが、非アクティブにすることもできます。非アクティブの場合はゲームオブジェクトにアタッチされているすべてのコンポーネントがオフになります。これは一般的には見えない状態になり、通常のコールバックや、UpdateFixedUpdate などのイベントを受け取らないことを意味します。

ゲームオブジェクトがアクティブ状態であるかは、ゲームオブジェクトの名前の左にあるチェックボックスで示されます。これは GameObject.SetActive を使用して制御できます。

GameObject.activeSelf を使用して、ゲームオブジェクトの現在のアクティブ状態を読み取ることもできます。シーン内でゲームオブジェクトが実際にアクティブかどうかを読み取るには、GameObject.activeInHierarchy を使用します。ゲームオブジェクトが実際にアクティブであるかどうかは、ゲームオブジェクト自体のアクティブ状態とすべての親のアクティブ状態によって決定されるため、GameObject.activeInHierarchy が必要になります。ゲームオブジェクト自体がアクティブに設定されていても、その親のいずれかがアクティブでない場合は、ゲームオブジェクトはアクティブにはなりません。

静的状態

ゲームオブジェクトの静的状態
ゲームオブジェクトの静的状態

グローバルイルミネーション、オクルージョン、バッチ処理、ナビゲーション、リフレクションプローブなど、Unity のシステムの中には、ゲームオブジェクトの静的な状態に依存するものがあります。GameObjectUtility.SetStaticEditorFlags を使用することで、どの Unity システムでゲームオブジェクトを静的と見なすかを制御できます。詳細については、静的ゲームオブジェクトを参照してください。

Tag と Layer

ゲームオブジェクトの Tag および Layer フィールド
ゲームオブジェクトの Tag および Layer フィールド

Tag (タグ) は、シーン内のゲームオブジェクトの種類をマークして識別する方法です。Layer (レイヤー) は似ていますが、レンダリング物理的衝突などの特定のビルトインアクションから、ゲームオブジェクトのグループを加えたり、除外したりするための別の方法です。

エディターでのタグやレイヤーの使用方法については、メインユーザーマニュアルのタグレイヤーの頁を参照してください。

タグとレイヤーの値は、GameObject.tag および GameObject.layer のプロパティを使用してスクリプトで変更できます。また、ゲームオブジェクトのタグは CompareTag メソッドを使用して効率的に確認することもできます。このメソッドは、タグが存在するかどうかの検証を行いますが、メモリの割り当てはしません。

コンポーネントの追加と削除

ランタイムにコンポーネントを追加または削除できます。これは、ゲームオブジェクトを連続的に作成したり、ゲームオブジェクトの動作を変更したりする場合に便利です。なお、スクリプトコンポーネントや一部のビルトインコンポーネントは、破棄せずにスクリプトから enable または disable にすることもできます。

ランタイムにコンポーネントを追加する最善の方法は、AddComponent<Type> を使用して、コンポーネントのタイプを山かっこで囲って指定することです。コンポーネントを削除するには、コンポーネント自体に Object.Destroy メソッドを使用する必要があります。

コンポーネントへのアクセス

最も単純なケースは、ゲームオブジェクト上のスクリプトが、同じゲームオブジェクトにアタッチされた別のコンポーネントにアクセスしなければならない場合です (ゲームオブジェクトにアタッチされた他のスクリプトもコンポーネントであることに注意してください)。これを行うための最初のステップは、使用するコンポーネントインスタンスへの参照を取得することです。これは GetComponent メソッドを使用して実行します。通常、コンポーネントオブジェクトを変数に割り当てたい場合は、以下のコードを使用します。この例では、スクリプトは同じゲームオブジェクト上の Rigidbody コンポーネントへの参照を取得します。

void Start ()
{
    Rigidbody rb = GetComponent<Rigidbody>();
}

コンポーネントインスタンスへの参照が取得できた後は、インスペクター上で行うのと同様にプロパティーの値を設定できます。

void Start ()
{
    Rigidbody rb = GetComponent<Rigidbody>();

    // Change the mass of the object's Rigidbody.
    rb.mass = 10f;
}

また、例えばコンポーネントリファレンスのメソッドを呼び出すこともできます。

void Start ()
{
    Rigidbody rb = GetComponent<Rigidbody>();

    // Add a force to the Rigidbody.
    rb.AddForce(Vector3.up * 10f);
}

ノート: 同じゲームオブジェクトに複数のカスタムスクリプトをアタッチすることができます。あるスクリプトから別のスクリプトへアクセスする必要がある場合は、通常どおり GetComponent 関数を使用し、スクリプトクラスの名前 (またはファイル名) を使用して、必要なコンポーネント型を指定するだけです。

ゲームオブジェクトに実際に追加されていないコンポーネント型を取得しようとすると、GetComponent は null を返します。null オブジェクトの値を変更しようとすると、ランタイムに null 参照エラーが発生します。

他のゲームオブジェクトのコンポーネントへのアクセス

スクリプトは単独で動作することもありますが、他のゲームオブジェクトや、より一般的には、他のゲームオブジェクト上のコンポーネントを操作することがよくあります。例えば、料理ゲームでシェフがコンロの位置を知る必要があるとします。Unity では、他のオブジェクトを取得するためのさまざまな方法が用意されていますので、状況に応じて使い分けてください。

Inspector の変数を使ってゲームオブジェクトにリンクする

関連するゲームオブジェクトを見つけるもっとも簡単な方法は public であるゲームオブジェクト変数をスクリプトに加えることです。

public class Chef : MonoBehaviour
{
    public GameObject stove;

    // Other variables and functions...
}

この変数は、Inspector で GameObject フィールドとして表示されます。

この変数に、シーンや Hierarchy ウィンドウからオブジェクトをドラッグして割り当てることができます。

プレハブを Project ウィンドウから Inspector ウィンドウの GameObject フィールドにドラッグする
プレハブを Project ウィンドウから Inspector ウィンドウの GameObject フィールドにドラッグする

このオブジェクトは他と同様に GetComponent 関数およびコンポーネントにアクセスできる変数を利用できます。そのため、以下のようなコードを使用できます。

public class Chef : MonoBehaviour {

    public GameObject stove;

    void Start() {
        // Start the chef 2 units in front of the stove.
        transform.position = stove.transform.position + Vector3.forward * 2f;
    }
}

さらに、スクリプトの中でコンポーネント型の public である変数を宣言すると、コンポーネントがアタッチされている任意のゲームオブジェクトをその上にドラッグできます。これはゲームオブジェクト自身ではなくコンポーネントに直接アクセスします。

public Transform playerTransform;

変数でオブジェクトをリンクさせることは、永続的に関連する個々のオブジェクトを処理するときに非常に便利です。配列の変数を使用して、同じ型の複数のオブジェクトをリンクさせることができますが、この関連付けは、ランタイムではなく Unity エディターで行う必要があります。多くの場合、オブジェクトの検索はランタイムに行うと便利です。Unity は、以下に示す 2 つの基本的な方法を提供しています。

子ゲームオブジェクトを検索する

ゲームのシーンでは、アイテム、ウェイポイント、障害物など、同じ種類の複数のゲームオブジェクトを使用することがあります。これらのオブジェクトを、監視または反応する特定のスクリプトによって追跡しなければならないことがあります (例えば、すべてのウェイポイントを、経路検索スクリプトで使用可能にする必要があるかも知れません)。変数を使用してこれらのゲームオブジェクトを関連付けることは可能ですが、新しいウェイポイントを 1 つずつスクリプト上の変数にドラッグする必要がある場合、設計面での処理が面倒になります。同様に、ウェイポイントを削除する場合に、欠けているゲームオブジェクトへの変数の参照を削除する必要があります。このような場合、しばしば、ゲームオブジェクトの群をすべて 1 つの親ゲームオブジェクトの子にすることによって管理する方が良いことがあります。子のゲームオブジェクトは親の Transform コンポーネントを使用して取得できます (なぜなら、すべてのゲームオブジェクトには暗示的に Transform があるからです)。

using UnityEngine;

public class WaypointManager : MonoBehaviour {
    public Transform[] waypoints;

    void Start()
    {
        waypoints = new Transform[transform.childCount];
        int i = 0;

        foreach (Transform t in transform)
        {
            waypoints[i++] = t;
        }
    }
}

名前を指定して特定の子オブジェクトを見つけるには Transform.Find メソッドを使用します。 transform.Find("Frying Pan");

これは、ゲーム中に追加や削除が可能な子ゲームオブジェクトを持つゲームオブジェクトの場合に便利です。ゲーム中に手に取ったり置いたりできる道具などは、この良い例です。

メッセージの送信とブロードキャスト

プロジェクトの編集中に、Inspector でゲームオブジェクト間の参照を設定することができます。ただし、事前に設定できない場合もあります (例えば、ゲーム内のキャラクターに最も近いアイテムを探す場合や、シーンがロードされた後にインスタンス化されたゲームオブジェクトを参照する場合)。このような場合は、ランタイムにゲームオブジェクト間の参照を見つけたり、メッセージを送信したりすることができます。

BroadcastMessage は、そのメソッドが実装されるべき場所を特定せずに、呼び出しを名前付きメソッドに送信できます。BroadcastMessage は、特定のゲームオブジェクトやその子のすべての MonoBehaviour の名前付きメソッドを呼び出すことができます。任意で、少なくとも 1 つのレシーバーを必要とすることを選択できます (エラーが発生する場合もあります)。

SendMessage はもう少し具体的で、当該ゲームオブジェクトの名前付きメソッドへの呼び出しのみを送信し、その子へは送信しません。

SendMessageUpwards も似ていますが、ゲームオブジェクトとそのすべての_親_の名前付きメソッドに呼び出しを送ります。

名前やタグによるゲームオブジェクトの検索

ゲームオブジェクトを認識する情報がある限り、シーンの階層内でゲームオブジェクトを見つけることは常に可能です。名前を指定して個々のオブジェクトを取得するには GameObject.Find 関数を使用します:

GameObject player;

void Start()
{
    player = GameObject.Find("MainHeroCharacter");
}

また、オブジェクトまたはオブジェクトのコレクションを、タグを使用して見つけるには、GameObject.FindWithTag メソッドおよび GameObject.FindGameObjectsWithTag メソッドを使用します。

例えば、1 人のシェフキャラクターがいる料理ゲームで、キッチンには複数のコンロがある場合 (それぞれ “Stove” (コンロ) というタグがついています)。

GameObject chef;
GameObject[] stoves;

void Start()
{
    chef = GameObject.FindWithTag("Chef");
    stoves = GameObject.FindGameObjectsWithTag("Stove");
}

ゲームオブジェクトの作成と破棄

プロジェクトの実行中に、ゲームオブジェクトを作成したり破棄したりすることができます。Unity では、既存のオブジェクトの新しいコピーを作成する Instantiate メソッドを使ってゲームオブジェクトを作成します。

ゲームオブジェクトをインスタンス化する方法の詳細と例については、ランタイムのプレハブのインスタンス化を参照してください。

Destroy メソッドは、フレーム更新の終了後、または任意で少しの遅延後にオブジェクトを破棄します。

void OnCollisionEnter(Collision otherObj) {
    if (otherObj.gameObject.tag == "Garbage can") {
        Destroy(gameObject, 0.5f);
    }
}

Destroy 関数は、ゲームオブジェクト自体に影響を与えずに、個々のコンポーネントを破棄することができます。よくある間違いは、this と記述することで、このスクリプトがアタッチされたゲームオブジェクトを破棄できると考えることです。

 Destroy(this);

this は、ゲームオブジェクトではなくスクリプトを表します。実際には、これを呼び出したスクリプトコンポーネントが破棄されるだけで、ゲームオブジェクトはそのまま残りますが、スクリプトコンポーネントは削除されます。

プリミティブ

GameObject クラスは、Unity の GameObject メニューで利用可能なオプションの代わりに、スクリプトベースでプリミティブなオブジェクトを作成することができます。

Unity のビルトインプリミティブのインスタンスを作成するには、GameObject.CreatePrimitive を使用します。これは、指定したタイプのプリミティブをインスタンス化します。使用できるプリミティブなタイプは、スフィアカプセルシリンダーキューブ平面クアッドです。

Unity の GameObject メニューで利用できるプリミティブ形状
Unity の GameObject メニューで利用できるプリミティブ形状

追加リソース

ゲームオブジェクトの基礎
Transform