【Unity】Unityコンポーネント連携の要!GetComponentを使いこなす

作成: 2025-12-07最終更新: 2026-07-13

他のコンポーネントの機能を使いたい時に必須のメソッド、GetComponent。基本的な使い方から、子や親オブジェクトからの取得、パフォーマンスを意識したキャッシュ方法まで、徹底的に解説します。

「スクリプトからRigidbodyを動かしたい」「ぶつかった相手のHPを減らしたい」——コンポーネント同士を連携させようとしたとき、最初に必要になるのが「相手の部品をどうやって手に入れるか」です。その答えが GetComponent<T>() です。

Unityのコンポーネント指向設計では、機能は部品(コンポーネント)に分かれています。GetComponentはその部品を取り出すための基本メソッドで、スクリプト連携の第一歩。この記事では基本の使い方から、パフォーマンスを左右する「キャッシュ」の鉄則、関連メソッドまでを解説します。

GetComponentのイメージ。スクリプトが同じGameObjectの中から目的の部品を探して取り出す

この記事でわかること

  • GetComponent<T>()で同じオブジェクトの部品を取得する方法
  • なぜ「キャッシュ」が鉄則なのか(毎フレーム呼ぶとどうなるか)
  • 検索範囲が違うGetComponentInChildren/InParent
  • nullチェックをスマートに書けるTryGetComponent

Sponsored

GetComponentの基本的な使い方

GetComponent<T>()は、そのスクリプトがアタッチされているのと同じゲームオブジェクトに存在する、指定した型Tのコンポーネントを検索し、その参照(インスタンス)を返します。Tの部分には、取得したいコンポーネントのクラス名を指定します。

イメージは「同じ器の中の部品棚から、型を指定して部品を取り出す」操作です。

GetComponentの概念図。スクリプトが同じGameObjectの部品一覧からRigidbodyを型指定で探し出し、参照を受け取る

組み込みコンポーネントの取得

例えば、物理演算のためにRigidbodyコンポーネントをスクリプトから操作したい場合、以下のように記述します。

using UnityEngine;

// このスクリプトをアタッチするGameObjectには、事前にRigidbodyコンポーネントを追加しておく
[RequireComponent(typeof(Rigidbody))]
public class PlayerPhysics : MonoBehaviour
{
    private Rigidbody rb;

    void Start()
    {
        // 同じGameObjectにアタッチされているRigidbodyコンポーネントを取得
        rb = GetComponent<Rigidbody>();

        // 取得したRigidbodyのプロパティを変更する
        if (rb != null) // 取得できたか確認するのが安全
        {
            rb.useGravity = true;
            rb.mass = 1.5f;
        }
        else
        {
            Debug.LogError("Rigidbodyコンポーネントが見つかりません!");
        }
    }

    void FixedUpdate()
    {
        // 取得したRigidbodyを使って力を加える
        rb.AddForce(Vector3.up * 10f);
    }
}

[RequireComponent(typeof(Rigidbody))]という属性をクラスの前に追加しておくと、このスクリプトをアタッチした際にRigidbodyコンポーネントがなければ自動的に追加してくれるため、取得し忘れを防ぐのに便利です。

自作スクリプトコンポーネントの取得

同様に、自分で作成した他のスクリプトコンポーネントを取得することもできます。これにより、スクリプト間で関数を呼び出したり、変数を参照したりできます。

// PlayerHealth.cs
using UnityEngine;
public class PlayerHealth : MonoBehaviour
{
    public int currentHealth = 100;

    public void TakeDamage(int damage)
    {
        currentHealth -= damage;
        Debug.Log("ダメージを受けた! 残りHP: " + currentHealth);
    }
}

// Enemy.cs
using UnityEngine;
public class Enemy : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        // 衝突した相手が"Player"タグを持つオブジェクトなら
        if (collision.gameObject.CompareTag("Player"))
        {
            // 相手のGameObjectからPlayerHealthコンポーネントを取得
            PlayerHealth playerHealth = collision.gameObject.GetComponent<PlayerHealth>();

            // 取得したコンポーネントの公開メソッドを呼び出す
            if (playerHealth != null)
            {
                playerHealth.TakeDamage(10);
            }
        }
    }
}
Sponsored

パフォーマンスの重要性:キャッシュしよう!

GetComponentは便利なメソッドですが、 実行にコストがかかる処理 であることを常に意識する必要があります。Unityは指定されたコンポーネントを見つけるために、ゲームオブジェクトにアタッチされているすべてのコンポーネントを検索します。

この処理をUpdate()のような毎フレーム呼び出される関数の中で実行すると、フレームごとに不要な検索処理が走り、パフォーマンスの低下に繋がります。

ただし「GetComponentは絶対悪」ではありません。1回や数回の呼び出しは誤差の範囲で、問題になるのは 毎フレーム×大量オブジェクトの繰り返し(ホットパス)だけです。「遅い気がする」で書き方を歪める前に、Profiler で実測して判断する癖をつけましょう。

ベストプラクティスは、Awake()またはStart()で一度だけGetComponentを呼び出し、その結果をメンバ変数に保存(キャッシュ)しておくことです。

例えるなら、毎フレーム倉庫まで工具を探しに行くのではなく、最初に1回だけ取りに行ってポケット(変数)に入れておき、以後はポケットから出して使うイメージです。

GetComponentのキャッシュの実例図。悪い例は毎フレーム倉庫へ部品を探しに行って疲れてしまう。良い例は最初に1回だけ取得してポケット(変数)に入れ、以後はそこから使う
// 悪い例:Update内で毎フレームGetComponentを呼んでいる
void Update()
{
    GetComponent<Rigidbody>().AddForce(Vector3.up);
}

// 良い例:Startでキャッシュし、Updateではその変数を使う
private Rigidbody rb;
void Start()
{
    rb = GetComponent<Rigidbody>();
}
void Update()
{
    rb.AddForce(Vector3.up);
}

この「キャッシュ」のテクニックは、Unityプログラミングにおける最も基本的で重要な最適化の一つです。

GetComponentには、検索範囲が異なるいくつかのバリエーションがあります。

  • GetComponentInChildren<T>(): 自分自身、または 子オブジェクト を検索し、最初に見つかったT型のコンポーネントを返します。
  • GetComponentInParent<T>(): 自分自身、または 親オブジェクト を遡って検索し、最初に見つかったT型のコンポーネントを返します。
  • GetComponents<T>(): 同じゲームオブジェクトにアタッチされている、 すべての T型のコンポーネントを配列で返します。
GetComponent系メソッドの検索範囲の比較図。GetComponentは自分だけ、GetComponentInChildrenは自分と子、GetComponentInParentは自分と親を検索する

これらのメソッドも同様にコストがかかるため、必要な場合を除き、多用は避けるべきです。

実戦では、この3つの発展形もよく登場します。

  • 非アクティブな子も含めて探す: GetComponentInChildren<T>(true)のように引数へtrueを渡すと、 非アクティブな子オブジェクトも検索対象 になります(デフォルトでは飛ばされます)。「隠してあるUIパーツを取得したらnullだった」の定番原因と解決策です。
  • 子のColliderから親のHealthへさかのぼる: 敵の頭・胴・脚に別々のColliderを持たせるヒット判定では、弾が当たった 子オブジェクト側からGetComponentInParent<EnemyHealth>()で親の体力へ届ける のが定石です。どの部位に当たっても、ダメージの届け先が1つにまとまります。
  • インターフェースでも取得できる: 型引数にはGetComponent<IDamageable>()のように インターフェース も指定できます。「プレイヤーでも木箱でも、IDamageableを実装していれば同じコードでダメージを与える」という柔軟な設計への入り口です。

より安全な書き方: TryGetComponent

Unity 2019.2以降では、TryGetComponent<T>(out T component)というメソッドが使えます。これはGetComponentと似ていますが、コンポーネントが見つかったかどうかをbool値で返し、見つかった場合はout引数にその参照を格納します。nullチェックをより簡潔に書くことができます。

// GetComponentの場合
Rigidbody rb = GetComponent<Rigidbody>();
if (rb != null)
{
    // 処理
}

// TryGetComponentの場合
if (TryGetComponent<Rigidbody>(out Rigidbody rb))
{
    // 処理
}

おまけ:先に知っておくと良いこと

GetComponentに慣れてきたら、次の視点も持っておくと設計が一段良くなります。

  • 別のオブジェクトの参照は、まずInspector割り当てを検討: GetComponentは「同じオブジェクトの中」の部品を取る道具です。別のオブジェクトを参照したいときは、[SerializeField]で変数を公開してInspectorからドラッグ&ドロップで割り当てるのが、最も速くて安全な第一候補です。
  • 参照だらけになってきたら疎結合設計へ: あちこちでGetComponentし合う設計は、オブジェクトが増えると絡まっていきます。 イベントとデリゲート を使うと「相手を知らなくても通知できる」疎結合な設計にできます。イベントとデリゲートの記事 で解説しています。
  • [RequireComponent]のような属性を知る: この記事でも登場した[RequireComponent]Attribute(属性) という仕組みの一例で、他にも便利な属性がたくさんあります。Attribute活用ガイド でまとめて学べます。

まとめ

GetComponentは、Unityのコンポーネント同士を繋ぎ、複雑なインタラクションを生み出すための鍵となるメソッドです。

  • GetComponent<T>(): 同じゲームオブジェクト内の他のコンポーネントを取得する基本。
  • キャッシュが命: Start()Awake()で取得し、変数に保存して使い回すのが鉄則。
  • GetComponentInChildren, GetComponentInParent: 親子関係にあるオブジェクトのコンポーネントも取得できるが、コストを意識する。
  • TryGetComponent: nullチェックをよりスマートに記述できる新しい選択肢。

このメソッドの役割と正しい使い方をマスターすれば、あなたのUnityプログラミングスキルは格段に向上するでしょう。