「スクリプトからRigidbodyを動かしたい」「ぶつかった相手のHPを減らしたい」——コンポーネント同士を連携させようとしたとき、最初に必要になるのが「相手の部品をどうやって手に入れるか」です。その答えが GetComponent<T>() です。
Unityのコンポーネント指向設計では、機能は部品(コンポーネント)に分かれています。GetComponentはその部品を取り出すための基本メソッドで、スクリプト連携の第一歩。この記事では基本の使い方から、パフォーマンスを左右する「キャッシュ」の鉄則、関連メソッドまでを解説します。
この記事でわかること
GetComponent<T>()で同じオブジェクトの部品を取得する方法- なぜ「キャッシュ」が鉄則なのか(毎フレーム呼ぶとどうなるか)
- 検索範囲が違う
GetComponentInChildren/InParentnullチェックをスマートに書けるTryGetComponent
GetComponentの基本的な使い方
GetComponent<T>()は、そのスクリプトがアタッチされているのと同じゲームオブジェクトに存在する、指定した型Tのコンポーネントを検索し、その参照(インスタンス)を返します。Tの部分には、取得したいコンポーネントのクラス名を指定します。
イメージは「同じ器の中の部品棚から、型を指定して部品を取り出す」操作です。

組み込みコンポーネントの取得
例えば、物理演算のために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);
}
}
}
}
パフォーマンスの重要性:キャッシュしよう!
GetComponentは便利なメソッドですが、 実行にコストがかかる処理 であることを常に意識する必要があります。Unityは指定されたコンポーネントを見つけるために、ゲームオブジェクトにアタッチされているすべてのコンポーネントを検索します。
この処理をUpdate()のような毎フレーム呼び出される関数の中で実行すると、フレームごとに不要な検索処理が走り、パフォーマンスの低下に繋がります。
ただし「GetComponentは絶対悪」ではありません。1回や数回の呼び出しは誤差の範囲で、問題になるのは 毎フレーム×大量オブジェクトの繰り返し(ホットパス)だけです。「遅い気がする」で書き方を歪める前に、Profiler で実測して判断する癖をつけましょう。
ベストプラクティスは、Awake()またはStart()で一度だけ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型のコンポーネントを配列で返します。

これらのメソッドも同様にコストがかかるため、必要な場合を除き、多用は避けるべきです。
実戦では、この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プログラミングスキルは格段に向上するでしょう。