疑問
transform を取得するために以下のような様々な書き方ができるが、これらの違いは何なのだろうか?
this.gameObject.GetComponent<Transform>()
gameObject.GetComponent<Transform>()
GetComponent<Transform>()
transform
結論
- 得られるオブジェクトはどれも同じ(当然)
- スピードが違う
- 4 >> 3 > 2 = 1
前提:Unity におけるクラスの継承関係
- Object > Component > Behaviour > MonoBehaviour
- MonoBehaviour クラスは Component クラスを継承している
(1) GetComponent<>()
のありか
-
GetComponent<>()
は GameObject クラスで 定義されている - Component クラスは、自身の属する GameObject への参照をメンバーとして 持っている
- つまり、それを継承した MonoBehaviour を継承したクラスでは、以下のように Transform を取得可能
1つ目の記法
this.gameObject.GetComponent<Transform>()
(2) this
は省略可能
- C# の仕様で、自身に属するメンバーを参照する場合
this
は省略できる
2つ目の記法
gameObject.GetComponent<Transform>()
(3) もうひとつの GetComponent<>()
- 実は
GetComponent<>()
は Component クラスにも 定義されている(単純に便利さのため) - つまり、それを継承した MonoBehaviour を継承したクラスでは、以下のように Transform を取得可能
-
gameObject
を経由しなくて済む分、こちらの方が高速なもよう
-
3つ目の記法
GetComponent<Transform>()
(4) transform
は特別
- Component クラスには
transform
なるプロパティが 定義されている -
transform
は専用の内部関数でコンポーネントを取得しているため、高速-
GetComponent<>()
のようにコンポーネントの検索コストがかからない
-
4つ目の記法
transform
補足:ほかのコンポーネントは「専用の内部関数」で取得できないの?
- できない
- Component クラスは
tranform
以外にも様々なコンポーネントへのショートカットを持っているcamera
rigidbody
- ...
- しかしこれらは 内部で
GetComponent<>()
を呼び出している にすぎない- それどころか
transform
以外のショートカットは最近のバージョンで非推奨になった
- それどころか
- Transform は特によく使うコンポーネントなので、特別に高速なアクセス手段が用意されたのではないか?
検証
- 以下のスクリプトを適当なオブジェクトにアタッチしてシーンを実行すれば、速度が検証できる
検証用スクリプト
using UnityEngine;
using System.Diagnostics;
public class NewBehaviourScript : MonoBehaviour {
// Use this for initialization
void Start () {
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
sw.Start();
for (int i = 0; i < 10000000; ++i)
{
Transform t = this.gameObject.GetComponent<Transform>(); // => 約 0.73 秒
// Transform t = gameObject.GetComponent<Transform>(); // => 約 0.73 秒
// Transform t = GetComponent<Transform>(); // => 約 0.53 秒
// Transform t = transform; // => 約 0.24 秒
}
sw.Stop();
UnityEngine.Debug.Log(sw.Elapsed);
}
}
補足: 最速はキャッシュ
- 一度取得した Transform をローカル変数に入れて使い回せるなら、それがもちろん最速