RequireComponentとは?

RequireComponentは、あるコンポーネントが動作するために必要な別のコンポーネントを宣言できる属性です。

この属性を付けたクラスをGameObjectに追加すると、依存先のコンポーネントが自動的にアタッチされます。

また、依存先のコンポーネントはインスペクタ上から単独で削除できなくなります。

基本的な使い方

典型的な例として、Rigidbodyを必要とするスクリプトを書いてみます。

クラス定義の直前に[RequireComponent(typeof(Rigidbody))]と記述します。

using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class PlayerMover : MonoBehaviour
{
    [SerializeField] private float _speed = 5f;

    private Rigidbody _rigidbody;

    private void Awake()
    {
        // 必ずアタッチされているので安全に取得できる
        _rigidbody = GetComponent<Rigidbody>();
    }

    private void FixedUpdate()
    {
        // 入力に応じて移動
        var input = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
        // Unity 6以降ではlinearVelocityプロパティを使用(Unity 2022以前はvelocity)
        _rigidbody.linearVelocity = input * _speed;
    }
}

このスクリプトをGameObjectにアタッチすると、Rigidbodyが無ければ自動で追加されます。

複数のコンポーネントを指定する

RequireComponentは、1つの属性で最大3つまで依存コンポーネントを同時に指定できます。

3つ指定する場合は、次のようにtypeofをカンマで並べます。

[RequireComponent(typeof(Rigidbody), typeof(BoxCollider), typeof(AudioSource))]
public class PhysicsObject : MonoBehaviour
{
}

例えばRigidbodyBoxColliderをどちらも必須にしたい場合は、次のように書きます。

using UnityEngine;

[RequireComponent(typeof(Rigidbody), typeof(BoxCollider))]
public class PhysicsObject : MonoBehaviour
{
    private Rigidbody _rigidbody;
    private BoxCollider _collider;

    private void Awake()
    {
        // 両方ともアタッチが保証されている
        _rigidbody = GetComponent<Rigidbody>();
        _collider = GetComponent<BoxCollider>();
    }
}

4つ以上の依存を表現したい場合は、先ほどのtypeofを並べる書き方では対応できません。属性自体を複数行スタックして記述します。

[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(BoxCollider))]
[RequireComponent(typeof(AudioSource))]
[RequireComponent(typeof(MeshRenderer))]
public class PhysicsObject : MonoBehaviour
{
}

「1属性につき最大3つ」「属性自体は何個でも重ねられる」と覚えておけば混乱しません。

RequireComponentを使うメリット

必須依存をコードで明示できる

どのコンポーネントが無いと動かないのかが、クラス定義を見るだけで分かります。

チーム開発でも「このスクリプト、何と一緒に付ければいいの?」という疑問が減りますね。

設定ミスを防げる

手作業で必要なコンポーネントを付け忘れる事故を防げます。

スクリプトをアタッチした瞬間に依存先も揃うので、NullReferenceExceptionの発生源を一つ潰せるわけです。

誤って削除されるのを防げる

依存先のコンポーネントは、インスペクタの削除メニューがブロックされます。

「とりあえずBoxColliderを消したら動かなくなった」みたいなトラブルを未然に防げるのが地味にありがたいところ。

注意点

既にアタッチされている場合は何もしない

依存先のコンポーネントが既にアタッチされている場合、RequireComponentは何も追加しません。

既存の設定値が上書きされる心配は無いから安心してね。

ランタイムでの追加には効かない

RequireComponentは、AddComponentでスクリプトを動的にアタッチするときには効きません。

ランタイムで組み立てる場合は、自分で必要なコンポーネントも明示的に追加しましょう。

using UnityEngine;

public class Spawner : MonoBehaviour
{
    private void Start()
    {
        var go = new GameObject("Enemy");

        // ランタイムでは依存先も手動で追加する必要がある
        go.AddComponent<Rigidbody>();
        go.AddComponent<BoxCollider>();
        go.AddComponent<PhysicsObject>();
    }
}

コンポーネントを削除する順序に注意

依存元のスクリプトを残したまま依存先のコンポーネントを削除しようとすると、警告ダイアログが出てきます。

「他のコンポーネントから必要とされている」というメッセージですね。

削除したいときは、先に依存元のスクリプトを外してから依存先を消す流れになります。

まとめ

RequireComponent属性について解説しました。

必須依存をコードで宣言できるので、設定ミスや削除事故を防げる地味に便利な属性です。

例えば物理挙動スクリプトを複数人で共有する場面では、RigidbodyColliderのアタッチ忘れを防げますし、UI系でButtonImageがセットになる構成にも向いています。

Animatorと連動するキャラクター制御スクリプトのように、依存先がはっきりしている場面でも有効ですね。

ランタイム時のAddComponentには効かない点だけ気をつけて、依存関係が決まっている場面で積極的に活用してみてください。