gameObject.GetComponent<Transform>() と transform の違い（または Unity における省略記法について）

## 疑問

transform を取得するために以下のような様々な書き方ができるが、これらの違いは何なのだろうか？

1. `this.gameObject.GetComponent<Transform>()`
1. `gameObject.GetComponent<Transform>()`
1. `GetComponent<Transform>()`
1. `transform`

## 結論

* 得られるオブジェクトはどれも同じ（当然）
* スピードが違う
    * 4 >> 3 > 2 = 1

![routing.png](https://qiita-image-store.s3.amazonaws.com/0/66421/3397ad27-38a4-1264-1f0c-ad5dec47784d.png)

## 前提：Unity におけるクラスの継承関係

* Object > Component > Behaviour > MonoBehaviour
* MonoBehaviour クラスは Component クラスを継承している

## (1) `GetComponent<>()` のありか

* `GetComponent<>()` は GameObject クラスで [定義されている](https://docs.unity3d.com/ScriptReference/GameObject.GetComponent.html)
* Component クラスは、自身の属する GameObject への参照をメンバーとして [持っている](https://docs.unity3d.com/ScriptReference/Component-gameObject.html)
* つまり、それを継承した MonoBehaviour を継承したクラスでは、以下のように Transform を取得可能

```c#:1つ目の記法
this.gameObject.GetComponent<Transform>()
```

## (2) `this` は省略可能

* C# の仕様で、自身に属するメンバーを参照する場合 `this` は省略できる

```c#:2つ目の記法
gameObject.GetComponent<Transform>()
```

## (3) もうひとつの `GetComponent<>()`

* 実は `GetComponent<>()` は Component クラスにも [定義されている](https://docs.unity3d.com/ScriptReference/Component.GetComponent.html)（単純に便利さのため）
* つまり、それを継承した MonoBehaviour を継承したクラスでは、以下のように Transform を取得可能
    * `gameObject` を経由しなくて済む分、こちらの方が高速なもよう

```c#:3つ目の記法
GetComponent<Transform>()
```

## (4) `transform` は特別

* Component クラスには `transform` なるプロパティが [定義されている](https://docs.unity3d.com/ScriptReference/Component-transform.html)
* `transform` は[専用の内部関数でコンポーネントを取得している](http://gamedev.stackexchange.com/a/101524)ため、高速
    * `GetComponent<>()` のようにコンポーネントの検索コストがかからない

```c#:4つ目の記法
transform
```

### 補足：ほかのコンポーネントは「専用の内部関数」で取得できないの？

* できない
* Component クラスは `tranform` 以外にも様々なコンポーネントへのショートカットを持っている
    * `camera`
    * `rigidbody`
    * ...
* しかしこれらは [内部で `GetComponent<>()` を呼び出している](http://gamedev.stackexchange.com/a/101543) にすぎない
    * それどころか `transform` 以外のショートカットは最近のバージョンで非推奨になった
* Transform は特によく使うコンポーネントなので、特別に高速なアクセス手段が用意されたのではないか？

## 検証

* 以下のスクリプトを適当なオブジェクトにアタッチしてシーンを実行すれば、速度が検証できる

```c#:検証用スクリプト
    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 をローカル変数に入れて使い回せるなら、それがもちろん最速

## 参考
* [Whats the difference between the Component and GameObject classes and how they are related? - Unity Answers](http://answers.unity3d.com/questions/42472/whats-the-difference-between-the-component-and-gam.html)
* [c# - What are the differences between using "GetComponent<Transform>()" and this.transform? - Game Development Stack Exchange](http://gamedev.stackexchange.com/questions/101522/what-are-the-differences-between-using-getcomponenttransform-and-this-tran)
* [Unity5のコンポーネントキャッシュと僕の勘違い](http://unity-michi.com/post-508/)