GetComponentメソッド
UnityEngine
には、GetComponent
というメソッドがあります。
主にGameObject
にアタッチされているコンポーネントを取得するのに使用します。
GameObject
クラス、及びComponent
クラス内に実装されているので、
MonoBehaviour
を継承したコンポーネントクラス内からも呼ぶことが出来ます。
基本的な使い方
以下の例では、スクリプトがアタッチされているのと同じGameObjectにアタッチされているコンポーネントを取得できます。
private void Awake()
{
Rigidbody body = GetComponent<Rigidbody>();
}
特定のGameObject
,Transform
を指定してコンポーネントを取得する事も出来ます。
当たり判定用のイベント内ではこのような使い方をすることが多いのではないでしょうか。
private void OnCollisionEnter(Collision other)
{
var collider1 = other.gameObject.GetComponent<Collider>();
var collider2 = other.transform.GetComponent<Collider>();
}
GetComponent
という名前ですが、インターフェイスを取得することも出来ます。
IVisibleという適当なインターフェイスを用意しましたが、
以下の例では、GameObject
にアタッチされているコンポーネントのうちIVisible
というインターフェースを継承しているコンポーネントの
インターフェイスを取得します。
public interface IVisible
{
bool IsVisible { get; }
}
private IVisible GetVisible()
{
return GetComponent<IVisible>();
}
関連するメソッド
GetComponent
に関連するメソッドがいくつかあります。
これらを使うと、コンポーネントをまとめて取得したり、子のGameObject
から取得できたりします。
GetComponents
GameObject
にアタッチされている同種のコンポーネントをまとめて取得することが出来ます。
var components = GetComponents<Collider>();
GetComponentInChildren
GameObject
自身とヒエラルキー上の全ての子GameObject
にアタッチされているコンポーネントを取得することが出来ます。
引数にtrue
を渡すことで、非アクティブなGameObject
も対象になります。
false
を渡すか省略した場合、非アクティブなGameObject
からはコンポーネントを取得できません。
var component = GetComponentInChildren<Collider>(true);
GetComponentsInChildren
GameObject
自身とヒエラルキー上の全ての子GameObject
にアタッチされているコンポーネントをまとめて取得することが出来ます。
引数にtrue
を渡すことで、非アクティブなGameObject
も対象になります。
false
を渡すか省略した場合、非アクティブなGameObject
からはコンポーネントを取得できません。
var components = GetComponentsInChildren<Collider>(true);
GetComponentInParent
直接の親GameObject
にアタッチされているコンポーネントを取得します。
var component = GetComponentInParent<Collider>();
GetComponentsInParent
直接の親GameObject
にアタッチされているコンポーネントをまとめて取得します。
引数で非アクティブなオブジェクトも検索対象にするか選べます。
var components = GetComponentsInParent<Collider>(true);
TryGetComponent
TryGetComponent
は、Unity2019.2
から追加されたメソッドです。
コンポーネントが存在するかをチェックし、存在する場合はコンポーネントを返します。
if (TryGetComponent(out Collider collider))
{
// Colliderを取得できた
}
コンポーネントの存在をチェックするコードが読みやすくなり、より安全で効率的にコードを書くことが出来ます。
また、TryGetComponent
はビルド後のアプリ上ではGC Alloc
が発生しません。
気をつける点
GetComponent
系メソッドは便利ですが、パフォーマンスの面で気をつける必要があります。
開発の序盤は、GetComponents
で問題なかったとします。
開発が進むにつれGameObject
が沢山の子オブジェクトとコンポーネントを持つようになっていた場合、
検索する対象が増えるため負荷も増えていきます。
Update
メソッドなど頻繁に呼ばれるタイミングで使用するのは避けた方がいいでしょう。
必要であれば、Awake
,Start
メソッドのタイミングで事前にキャッシュしておくのがよいでしょう。
代替方法
一番いいのは、事前にSerializeField
に設定しておくことです。
// 1.必要な時にGetComponentで取得する
public class Stage : MonoBehaviour
{
private void Update()
{
var player = GetComponent<Player>();
}
}
// 2.事前にGetComponentnで取得する
public class Stage : MonoBehaviour
{
private Player _player;
private void Start()
{
_player = GetComponent<Player>();
}
}
// 3.事前にSerializeFieldに設定しておく
public class Stage : MonoBehaviour
{
[SerializeField] private Player _player;
}
事前に設定しておけば、取得するためのコードを書く必要もなくなり、
子オブジェクトやコンポーネントが増えてもパフォーマンスに影響も出ません。
まとめ
今回はGetComponent
関係について説明しました。
GetComponent
はUnity
でゲーム開発を行う上で重要なメソッドですが、
パフォーマンスに影響を与える可能性もあるため、その使い方には注意が必要です。
特に、頻繁に呼び出されるメソッド内での使用や、大量の子オブジェクトやコンポーネントを持つGameObject
での使用は避けた方が良いでしょう。
また、可能であればAwake
やStart
メソッドでコンポーネントをキャッシュするか、SerializeField
を利用して事前に設定しておくとベストです。
衝突時のイベントなどどうしても使用する場合には、TryGetComponent
を使うことも考えてみてください。