ドットインストールのUnity入門の補足説明

この記事は、筆者が大学でUnityを教えるにあたって、事前準備として夏休みの宿題として学生にドットインストールのUnity入門を学習させるための補足説明です。

学生用に書いたものですが他にも役に立つ人がいるかもしれないので公開します。

[ドットインストール - Unity入門](https://dotinstall.com/lessons/basic_unity_v2)


# この記事の目的

ドットインストールのレッスンを否定している訳ではなく、夏休みの宿題用の素晴らしい教材としてありがたく使わせていただいています。その上で、本当に何も知らない学生にとっていきなり出てくる様々な概念や用語について、さらに詳しく説明することでより理解度を深めることを目的としています。


# この記事の対象者

この記事はUnity入門のためにドットインストールで学ぶ、プログラミング初心者を対象にしています。


# 目次

この記事には以下のような構成でUnity入門について解説しています。カッコの中の#11などはドットインストールのレッスンの中で対応する動画の番号を示しています。

1. まずは一度レッスンを全部通してやってみる
2. スクリプトおよび GameObject の関連付けについて ([#11](https://dotinstall.com/lessons/basic_unity_v2/47311))
3. スクリプトを作成すると自動的に挿入されているコードについて ([#11](https://dotinstall.com/lessons/basic_unity_v2/47311))
4. 型についての補足説明 ([#12](https://dotinstall.com/lessons/basic_unity_v2/47312))
5. クラスについての補足説明 ([#12](https://dotinstall.com/lessons/basic_unity_v2/47312))
6. #12のスクリプトの補足説明 ([#12](https://dotinstall.com/lessons/basic_unity_v2/47312))
7. #14のスクリプトの補足説明 ([#14](https://dotinstall.com/lessons/basic_unity_v2/47314))
8. プレハブ(Prefab)って何？ ([#16](https://dotinstall.com/lessons/basic_unity_v2/47316))
9. なぜ空のGameObjectを作成するのか？ ([#16](https://dotinstall.com/lessons/basic_unity_v2/47316))
10. RigidBodyって何？ ([#19](https://dotinstall.com/lessons/basic_unity_v2/47319))
11. OnCollisionEnterって何？ ([#19](https://dotinstall.com/lessons/basic_unity_v2/47319))

# 1. まずは一度レッスンを全部通してやってみる

まずは頭の中に？がいっぱいになったとしてもとりあえず、言われるがままにレッスンを進めて最後までやってみてください。数時間で終わると思います。その後この記事を見ながら２周目をやるとかなり理解が深まると思います。

[ドットインストール Unity入門](https://dotinstall.com/lessons/basic_unity_v2)

# 2. スクリプトおよび GameObject の関連付けについて ([#11](https://dotinstall.com/lessons/basic_unity_v2/47311))

いきなり Add Component してスクリプトを作って、さらっと紐づけられていますが、はじめてUnityに触れる人にとっては以下のような疑問が出てくると思いますので補足として解説します。

### スクリプトって何？

「スクリプト」とはプログラミング言語（UnityではC#）で書かれたプログラムのことです。Unityでは（最初のうちは）１つの GameObject に対して１つのスクリプトを書いて、その GameObject の挙動を制御します。


### コンポーネントって何？

コンポーネントは、GameObject に対してさまざまな見た目や、機能、挙動を加えることができます。このレッスンではスクリプトをコンポーネントとしてGameObjectに追加していますが、GameObject の位置や大きさ、回転を指定する Transform、オブジェクトの色や質感を指定する Material などもコンポーネントの1種です。


### 紐づけるってどういうこと？

GameObject にコンポーネントとしてスクリプトを追加すると、GameObject とスクリプトが関連づけられた状態になります。その状態になってはじめて、スクリプトに紐づけられた GameObject がシーン上にあるときに、そのスクリプトが実行されます。スクリプトを書いただけでは実行されませんので注意してください。


翻訳が中途半端ですが、以下のUnity公式マニュアルでも解説されています。
https://docs.unity3d.com/ja/current/Manual/CreatingAndUsingScripts.html


# 3. スクリプトを作成すると自動的に挿入されているコードについて ([#11](https://dotinstall.com/lessons/basic_unity_v2/47311))

Unityでスクリプトを作成すると、自動的に以下のようなコードが書かれたスクリプトが作成されます。
この内容についてそれぞれ説明していきます。

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BallScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
```




### using

```C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
```

Unityのスクリプトではさまざまな機能が使えますが、それらはいきなり使うことはできず、使いたい機能を呼び出さなければいけません。例えば、スマホでは本当にいろんなことができますが、アプリをまったくインストールしていないスマホでは何もできないことと似ています。

C#では、さまざまな機能が「名前空間」というものの中にまとめられています。コンピュータのフォルダにのような概念です。これらの行では　`using` の後に続いて名前空間を記述することで、 `System.Collections` 、 `System.Collections.Generic` 、 `UnityEngine` という名前空間を利用するということを宣言しています。

「名前空間」という変な名前ですが、スクリプトを書いていると「Ball」とか「BallFactory」とか「speed」とかクラスや変数にいろんな名前を付けます。自分で適当に付けた名前と、Unityに標準で用意されている名前と被ってしまっても大丈夫なように、さまざまな機能が名前空間で分けられているのでちゃんと区別できるようになっています。なのでこの名前が被らないようにするという意味で「名前空間」（name space）という名前が付いています。


### UnityEngine
Unityで標準装備されている基本的なC#の部品がこの中にまとまっています。
以下のUnity公式スクリプトリファレンスにアクセスしてください。

https://docs.unity3d.com/ja/current/ScriptReference/index.html

左側の「UnityEngine」の「＋」をクリックして開いて、
<img width="380" alt="スクリーンショット 2019-08-23 22.05.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/49826073-98ed-e983-e173-202d84d2ab91.png">

その中にある「Classes」の「＋」をクリックすると UnityEngine の中にあるたくさんのC#の部品を確認することができます。
<img width="380" alt="スクリーンショット 2019-08-23 22.05.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/26cc469a-7875-3e61-f6ea-9dc9285aec73.png">

このようにUnityには大量の便利な機能（クラス）が用意されています。ただその全てを覚えることはできないので、分からないことがあれば、ますスクリプトリファレンスを見るようにしてください。


### セミコロン
`;`（セミコロン）はC#の命令の区切りです。それぞれの命令の最後には必ず `;` が必要です。これを書き忘れるとエラーになるので、スクリプトを実行したときにエラーが発生したときはまず `;` を忘れてないか確認してみましょう。

### コメント

```
// Start is called before the first frame update

// Update is called once per frame
```
スクリプトを書くときにちょっとしたメモを書いたり、書いたスクリプトを部分的に無効にしたいといった場合には、「コメント」を使います。Unityが生成するスクリプトにも上記のような解説がコメントとして記述されています。
コメントを書くには `//` と記述するとその行の `//` 以降の文字はコメントとなり、スクリプトを実行するときに無視されるようになります。 `//` は1行ずつしかコメントにできないので、複数行まとめてコメントにしたい場合は `/*` と書くと、そこから `*/` と記述するまでがコメントになります。

```
// １行コメント

/*
複数行の
コメント
です
*/
```

### クラス

```C#:PaddleScript.cs
public class PaddleScript : MonoBehaviour
{
    // クラスの中身
}
```
この行では `PaddleScript` というクラスを宣言しています。クラスはスクリプトで使うさまざまな部品のことで、あらかじめさまざまなC#標準のクラスやUnity標準のクラスが用意されており、ここで宣言しているように、自分で作ることもできます。

後ろの `: MonoBehaviour` の部分は、このクラスはUnityで標準装備されている `MonoBehaviour` というクラスの機能を継承するということを指定しています。機能を継承することで、もともとの `MonoBehaviour` が持っている機能にさらに自分で機能を追加した新しいクラスを作ることができます。

`MonoBehaviour` は `UnityEngine` という名前空間で定義されているので、これを利用するには1行目の `using UnityEngine;` が必要になります。宣言したクラスの中身のスクリプトはすべてここに書かれた中カッコ `{` から最後の中カッコ `}` の内側に記述します。

### メソッド
```C#:PaddleScript.cs
void Start()
{
    // メソッドの中身
}
```

ここではクラス宣言の内側に `Start` というメソッド（関数、ファンクションとも言う）を宣言しています。メソッドはクラスの持つ機能のことで、自由に名前をつけていくつでも作ることができます。ここで宣言している `Start` メソッドはもともと継承元の `MonoBehaviour` クラスで宣言されていて、紐づけられた GameObject が作成された時に一度だけ実行されます。

ここではその `Start` メソッドを上書きすることで、GameObject が作成されたときに実行したい独自の処理を記述することができます。メソッドの中身のスクリプトは、ここにかかれた中カッコ `{` からメソッドの終わりの中カッコ `}` の内側に記述します。

メソッドは何らかの処理を実行した後に、結果を返すことができますが、ここにある `void` は結果を何も返さないということを示しています。


### Updateメソッド
```C#:PaddleScript.cs
void Update()
{
    // メソッドの中身
}
```

ここは `Start` メソッドと同様に継承元の `MonoBehaviour` クラスで宣言されている  `Update` というメソッドを上書きしています。`Update` メソッドは 紐付けられた GameObject がシーンに配置されている間、画面が更新される度に実行されます。通常だと1秒間に60回ほど実行されます。



### インデントについて

```C#:PaddleScript.cs
public class BallScript : MonoBehaviour
{
    private float speed;
    // Start is called before the first frame update
    void Start()
    {
        speed = Random.Range(5f, 15f);
    }

    // Update is called once per frame
    void Update()
    {
        transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
    }
}
```
このスクリプトではクラスの宣言の後の中カッコ `{` 以降、クラス宣言の終わりの中カッコ `}` まで、それぞれの行の始まりが右に一段ずれています。また、クラス内のメソッド宣言の後の中カッコ `{` 以降さらに右にずれます。
こうやって、始まりの中カッコ `{` が入力される度に行の始まりを１段ずつ右にずらしていくことを「インデント」と言います。
インデントすることで、今クラス宣言の中身を書いているのか、メソッド宣言の中身を書いているのかが分かりやすくなります。逆に、インデントされていないスクリプトは長くなってくると解読が困難になるため、必ずインデントをする癖をつけましょう。

実際にはタブを入力することでインデントできるのですが、最近のエディタでは自動的にインデントしてくれるものが多いです。




少し古い記事ですが、Unityが最初に生成するスクリプトの中身について、この記事でもう少し詳しく解説されています。
https://qiita.com/JunShimura/items/3c2e23bb77cc9085bfda



# 4. 変数と型についての補足説明([#12](https://dotinstall.com/lessons/basic_unity_v2/47312))

### 変数について

プログラミングをする上でとても基本的な概念に「変数」があります。数学で出てくるx, yといった変数とは少し違います。プログラミングでは、数値や文字列など様々な値を扱いますが、そういう値を保持しておく箱のようなものがプログラミングにおける変数です。変数について簡単にまとめると以下のような特徴があります。

- 変数は値を保存したり読み出したりできる箱のようなもの
- 変数と言っても数値だけだはなく文字列やオブジェクトなどなんでも保存できる
- 変数には自由な名前をつけることができる
- 変数を作るには、宣言をする必要がある
- 変数には型という概念があり、宣言するときに型の指定が必要
- 変数に値を保存することを「代入」という

変数を宣言するには、型の後に変数名を記述します。

```C#
int x;
```

この例では `x` という名前で `int` という型の変数を宣言しています。（ `int` は整数値を扱う型）
変数に値を保存することを「代入」と言いますが、値を代入するには `=` を使います。

```C#
int x;
x = 2;
```

この例では1行目で `int` 型の変数 `x` を宣言して、2行目で `x` に `2` という値を代入しています。
値の代入は `=` の右側に記述された値が、左側に記述された変数に保存されます。必ず右→左です。左→右はありませんので注意してください。

また、変数の宣言と同時に値を代入して初期化することもできます。その場合は以下のように記述します。

```C#
int x = 2;
```

また、変数に値を代入する場合の `=` の左側に変数を使うこともできます。
以下の例では変数　`x` に　`2` を代入し、変数 `y` に　`x + 1` の計算結果を代入しているので、 `y` の中身は3になります。

```C#
int x = 2;
int y;
y = x + 1;
```


### `0f` の `f` って何？

```C#:PaddleScript.cs
transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
```
C#のスクリプトでは整数値や小数値、文字列などいろいろな値を扱います。それらはの値の種類を「型」と言います。
例えば整数を扱うには `int` という型を利用し、小数を扱うには精度の高い `double` とその半分の精度の `float` といった種類の型があります。
C#では `0` や `1` のような整数の値は自動的に int として扱われ、 `0.0` や `0.5` のように記述した値は自動的に `double` として扱われます。 `0f` や `0.5f` のように数値の後に `f` を付けるとその数値は `double` ではなく `float` として扱われるようになります。

ここで使われている `Vector3` は `double` ではなく `float` を扱うクラスなので、 `0` ではなく `0f` とする必要があります。（ドットインストールでは浮動小数点数を渡す決まりになっているので `f` を付けると解説されていますが、実際には浮動小数点数を渡すから `f` を付けるのではなく、 浮動小数点数の中でも `double` ではなくて `float` を渡す決まりになっているので `f` を付ける必要があるということになります）

# 5. クラスについての補足説明 ([#12](https://dotinstall.com/lessons/basic_unity_v2/47312))

Unityで書く1つのスクリプトは基本的に1つのクラスになります。クラスはスクリプトで扱うオブジェクトの型の種類の1つで、クラスを作ることで型を自分でつくることができます。クラスを作るとその型のオブジェクトをいくつでも作ることができ、そのオブジェクトのことを「インスタンス」と言います。

クラス（型）はオブジェクトの設計図のようなもので、それを元に実際に生成されたオブジェクトがインスタンスです。

<img width="420" alt="スクリーンショット 2019-08-27 20.32.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/9188e61a-6331-375a-c301-13622b353a87.png">


### いきなり出てくる `transform` って何？ 

```C#:PaddleScript.cs
transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
```

ここで書いている `PaddleScript` は `MonoBehaviour` というクラスの持つメソッド（機能）や変数を全て継承して、それに独自の機能を新たに追加しているクラスです。 `transform` は `MonoBehaviour` クラスが持つ変数の１つで位置情報や変形などに関する情報がまとめて格納されています。

Unity公式スクリプトリファレンスに書いてありますが `MonoBehaviour` クラスは `transform` という変数を持つと書いてあります。なので、 `MonoBehaviour` を継承している `PaddleScript` も変数 `transform` を持つことになります。

`MonoBehaviour` クラスのリファレンス（継承メンバーの変数のところに `transform` の記述がある）
https://docs.unity3d.com/ja/current/ScriptReference/MonoBehaviour.html

そしてそこをクリックすると `transform` は `Transform` というクラスの変数だということが分かります。

 <div style="text-align: center;"><img width="340" alt="スクリーンショット 2019-08-26 22.30.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/c4844347-1512-76e7-3572-df8aa3b905b4.png">
</div>

### `transform.position` って何？


```C#:PaddleScript.cs
transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
```
スクリプトリファレンスを見ると、 `Transform` クラスは `position` という変数を持っていて、この変数 `position` は Vector3 という型だということが分かります。

`Transform` クラスのリファレンス
https://docs.unity3d.com/ja/current/ScriptReference/Transform.html


`Transform` クラスの変数 `position` のリファレンス
https://docs.unity3d.com/ja/current/ScriptReference/Transform-position.html

なので先ほどの図に `position` を付け加えると以下のような相関関係になります。
 <div style="text-align: center;">
<img width="515" alt="スクリーンショット 2019-08-26 22.22.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/b3f82ade-cd20-d26b-4d81-7165adc0a067.png">
</div>

### `Vector3` って何？


```C#:PaddleScript.cs
transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
```

`Vector3` は`x`, `y`, `z` の３つの `float` の値をまとめて扱えるので3D空間での位置情報を扱うのに便利なオブジェクトです。`transform.position` の型は Vector3 なので、ここでは Vector3 を使う必要があります。
（`Vector3` はクラスではなく構造体というものですが、今さらに新たな概念を理解すると大変だし、ほぼクラスと同じように使えるので今はほぼクラスみたいなものだと思ってもらって大丈夫です。）

`Vector3` の公式リファレンス
https://docs.unity3d.com/ja/current/ScriptReference/Vector3.html


### `new` って何？

```C#:PaddleScript.cs
transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
```

`new` はクラス（構造体も含む）のインスタンスを新しく作成する時に使うキーワードです。
`new` を使ってクラスのインスタンスを新しく作るときには「コンストラクタ」と言う特殊なメソッドが実行されます。コンストラクタはインスタンスが新しく作成されるときに最初にやっておくべき初期化処理をしたり、パラメータ（引数）を受け取ってインスタンスの持つ変数に値をセットするといった処理をします。
`new` キーワードを使ってクラスのインスタンスを作成するには、 `new` の後にクラス名（構造体名）を記述して、その後にカッコ `(` `)` を書いて、コンストラクタに渡すパラメータを書きます。

コンストラクタに渡すパラメータについて調べるには、`Vector3` の公式リファレンスを確認してください。
https://docs.unity3d.com/ja/current/ScriptReference/Vector3.html

「コンストラクタ」の部分の `Vector3` をクリックするとコンストラクタのページに移動します。
https://docs.unity3d.com/ja/current/ScriptReference/Vector3-ctor.html

`Vector3` のリファレンスを見てみるとコンストラクタで3つの `float` の値をパラメータとして受け取ることが分かります。

なので、

```C#
new Vector3(0f, 0f, 0f)
```
と書くと、`Vector3` のインスタンスを新たに1つ作成して、コンストラクタに `0f, 0f, 0f` を渡しているので、x, y, z が全部ゼロのVector3 のインスタンスが作成されます。


### `+=` って何？

```C#:PaddleScript.cs
transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
```

`transofrm.position` の後に　`+=` 、 `new Vector3`が続いていますが、これは、`PaddleScript` クラスのインスタンスが持っている変数 `transform` の `position` に `=` の右側で新しく作られる `Vector3` クラスのインスタンスを足しているということになります。

`transform.position` も `new Vector3` で作られるオブジェクトもどちらも `Vector3` のインスタンスで、それぞれのインスタンスの持つ x, y, z の変数が足し合わされた結果が `transform.position` に保存されます。

## 6. その他スクリプトの補足説明([#12](https://dotinstall.com/lessons/basic_unity_v2/47312))

### `Input` って何？

```C#:PaddleScript.cs
void Update()
{
    transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime * speed, 0f, 0f);
}
```

`Input` はUnityで、キーボードやマウス、タッチディスプレイ、ゲームパッド、ジョイスティックなどのユーザーのさまざまな入力を取得することができるクラスです。

UnityのInputで入力を扱う - Qiita
https://qiita.com/yando/items/c406690c9ad87ecfc8e5

Unity公式マニュアル - 一般的なゲーム入力
https://docs.unity3d.com/ja/current/Manual/ConventionalGameInput.html

`Input` のスクリプトリファレンス
https://docs.unity3d.com/ja/current/ScriptReference/Input.html


### `Input.GetAxis("Horizontal")` って何？


```C#:PaddleScript.cs
void Update()
{
    transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime * speed, 0f, 0f);
}
```

`Input.GetAxis("Horizontal")` はゲームコントローラーの十字キーやジョイスティックの水平方向の状態を `float` 型の数値として取得します。垂直方区の状態は `GetAxis` に渡すパラメータを `"Horizontal"` ではなく `"Vertical"` に変えることで取得できます。

`Input.GetAxis` のスクリプトリファレンス
https://docs.unity3d.com/ja/current/ScriptReference/Input.GetAxis.html

この部分の１行はとても長いので、スクリプトを以下のように書きかえてみましょう。

```C#:PaddleScript.cs
void Update()
{
    float horizontalAxis = Input.GetAxis("Horizontal");
    float x = horizontalAxis * Time.deltaTime * speed;
    transform.position += new Vector3(x, 0f, 0f);
    Debug.Log(horizontalAxis);
}
```

まず、 `float` 型の変数 `horizontalAxis` に `Input.GetAxis("Horizontal")` で取得したゲームコントローラーの状態を取得しています。キーボードのキーを何も押していないときには、変数 `horizontalAxis` には `0f` が入り、左キーを押しているときは `-1f` が、右キーを押しているときは `1f` が入ります。

次の行では、それに `Time.deltaTime` と `speed` をかけた値を `float` 型の変数 `x` に代入しています。

その次の行では　`new Vector3` でコンストラクタのパラメータに　`x` を渡しています。これらを1行で書いていましたが、こうやって分けて書くとよりわかりやすいと思います。

次の行の `Debug.Log(horizontalAxis);` をすることで、実行した時にキーボードの状態に応じて `horizontalAxis` の値が変化することがコンソールで確認できると思います。（この行は確認した後は不要なので消しましょう）

<img width="711" alt="スクリーンショット 2019-08-25 22.07.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/43d20e94-9efe-64fe-704a-159ce3d246df.png">


キーボードはゲームコントローラーがない場合にコントローラーの代わりに使うことができるので、`Input.GetAxis("Horizontal")` で矢印キーの状態が取得できます。

`Input.GetAxis("Horizontal")` を使っておけば、USBのゲームコントローラーなどUnityが対応するさまざまなコントローラーを接続した時にプログラムを書き変えることなく、そのままプレイできます。

### `Time.deltaTime` って何？


```C#:PaddleScript.cs
transform.position += new Vector3(Input.GetAxis("Horizontal") * Time.deltaTime, 0f, 0f);
```

`Time.deltaTime` は、前回のフレーム（前回 `Update` メソッドが実行されたタイミング）からの経過時間（秒）を取得することができます。 `Update` メソッドは必ずしも一定間隔で実行されるわけではありません。コンピュータの負荷によって遅くなったり早くなったりします。

例えば1フレームごとに1ピクセルずつ動くプログラムを書いた場合、フレームの間隔が安定して0.1秒だとすると1秒間に10回実行され、10ピクセル動くことになりますが、もしコンピュータの負荷によりフレームの実行間隔が遅くなり、1秒間に5回しか実行されなければ、5ピクセルしか動かないことになります。

<img width="560" alt="スクリーンショット 2019-08-27 10.33.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/bde88094-6a7d-83c4-4fd3-bbc06d9f7ed4.png">

このようにフレームごとに一定の値だけ動かすといったスクリプトを書くとフレームの実行間隔により見た目のスピードは一定ではなくなります。なので、フレームの実行回数によりオブジェクトを動かすのではなく、経過時間によりオブジェクトを動かす方が正しくスムーズにオブジェクトを動かすことができます。そのために `Time.deltaTime` を利用します。

<img width="560" alt="スクリーンショット 2019-08-27 10.33.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/6871ac6e-f43f-9634-78e0-81b1708bbc6b.png">

Unity公式マニュアル - タイムとフレームレートの管理
https://docs.unity3d.com/ja/current/Manual/TimeFrameManagement.html


## 7. #14のスクリプトの補足説明 ([#14](https://dotinstall.com/lessons/basic_unity_v2/47314))


### 変数 `speed` はなぜその場所に記述するのか？


```C#:PaddleScript.cs
public class PaddleScript : MonoBehaviour
{
    private float speed;

    // Start is called before the first frame update
    void Start()
    {
        speed = 5f;
    }
```

クラスの記述の決まりとして、`class` の宣言の後に中カッコがあり、その中にメソッドを記述しますが、`class` 宣言の中にメソッドと同列で変数を宣言すると、その変数は「インスタンス変数」としてそのクラスのインスタンスが持つ変数になります。ドットインストールの例で言うと、Ball の数だけそれぞれがこの `speed` という変数を持っていて、`Start()` でランダムな値が設定されるので、インスタンスごとに個別の値を保持しています。

<img width="515" alt="スクリーンショット 2019-08-27 20.41.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/84955b4f-8c3b-59fb-1fa3-3fea9ffd4d03.png">


### 変数のスコープ（有効範囲）について

変数にはスコープ（有効範囲）というものがあり、宣言する場所によってスコープが変わります。ここでは、クラス宣言の内側で変数 `speed` を宣言しています。こうすることで、このクラスのインスタンスが存在する限り、変数 `speed` も存在します。

```C#:PaddleScript.cs
public class PaddleScript : MonoBehaviour
{
    private float speed;
    void Start()
    {
        speed = 5f;
    }
}
```

メソッドの中で変数を宣言することもできます。ただし、メソッドの中で宣言した変数はそのメソッドの実行が終了した時点で破棄されてしまうので、メソッドの実行時に一時的に使いたいといった場合にメソッド内で変数を宣言します。

```C#:PaddleScript.cs
public class PaddleScript : MonoBehaviour
{
    void Start()
    {
        float speed;
        speed = 5f;
        // Start()メソッドはここまでなので、ここで変数 speed は破棄される
    }
    
    void Update()
    {
        // ここでは speed 変数は存在しない
    }
}
```



### `private` って何？


```C#:PaddleScript.cs
public class PaddleScript : MonoBehaviour
{
    private float speed;
```
クラスの持つインスタンス変数は、そのクラスの外側からアクセス可能にするか、そのクラス内でのみアクセスできるようにするかを設定できます。変数宣言の前に private と付けるとその変数にはクラス内からしかアクセスできないようになります。private の代わりに public とすると、その変数には外部からアクセスできるようになり、クラスの外部（他のクラスやUnityのInspectorなど）から値を参照したり変更したりすることができるようになります。


## 8. プレハブ(Prefab)って何？ ([#16](https://dotinstall.com/lessons/basic_unity_v2/47316))

ドットインストールではさらっと登場して使われているプレハブについて、とても重要な概念なのでもう少し説明しておきます。

プレハブは、同じような GameObject をたくさん配置して、それぞれを個別に動かしたいような場合のテンプレートのような機能です。スクリプトで使うクラスと似た概念です。

Ballのプレハブをドラッグ＆ドロップでシーンにたくさん配置するとヒエラルキービューでは青く表示されます。これはこのオブジェクトがプレハブから作られたことを意味します。

<img width="348" alt="スクリーンショット 2019-08-26 17.45.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/2deca678-d357-895c-305b-d8300f8b07c6.png">


これらの球体にまとめて変更を加えたければ、元のプレハブのScaleを変えればシーンに配置した全てのオブジェクトに反映されます。また、色を変えたければ、元のプレハブにマテリアルを適用することで全てのオブジェクトに反映されます。

<img width="622" alt="スクリーンショット 2019-08-26 17.52.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/bd0b7340-aea4-d4b7-a7dd-d87233da70e3.png">


ただ、これらのオブジェクトは個別にそれぞれの設定をすることも出来て、個別のオブジェクトのプロパティをプレハブのデフォルトの値から変更すると、それらは元のプレハブの設定を上書きした個別の値を持つことができます。

<img width="622" alt="スクリーンショット 2019-08-26 17.54.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/fecb65a9-b57d-931b-92d1-d9a81044dd74.png">


また、ドットインストールでやっているようにスクリプトからプレハブを元にオブジェクトをシーンに追加することもできます。

Unity公式マニュアル - プレハブ
https://docs.unity3d.com/ja/2018.1/Manual/Prefabs.html


## 9. なぜ空のGameObjectを作成するのか？ ([#16](https://dotinstall.com/lessons/basic_unity_v2/47316))

ドットインストールでは BallFactory という空の GameObject を作成し、そこの BallFactoryScript という名前でスクリプトを関連づけています。
このスクリプトは Ball のプレハブから 実際のシーンに Ball を生成して配置するためのスクリプトですが、スクリプトを作っただけでは実行することが出来ないので、スクリプトを実行するためだけの空の GameObject を生成して、それに関連付けすることで、スクリプトを実行できるようにしています。
また、Ballに関連付けられた BallScript は、BallFactoryScript から Ball のオブジェクトが生成される度に Start() が実行されて、画面上の Ball の数だけそれぞれの Update() が実行されます。


## 10. RigidBodyって何？([#19](https://dotinstall.com/lessons/basic_unity_v2/47319))

RigidBody はコンポーネントの1つで、 このコンポーネントを追加した GameObject は物理演算により動くようになります。物理演算によって動くということは、現実世界の物理の法則と同じように、Unityの3D空間で、重力により落下したり、他のオブジェクトと衝突して跳ね返ったり、空気抵抗を受けたりといったことをシミュレーションすることができます。

Inspector で RigidBody の設定項目を見てみると、重量や空気抵抗の大きさ、重力の影響を受けるかどうか、他のオブジェクトとの衝突を検知するかといった項目があります。これらを設定することで GameObject にさまざまな挙動をさせることができます。

<img width="343" alt="スクリーンショット 2019-08-26 18.07.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486013/904435ea-d70d-3887-86eb-4eb71cbe95eb.png">


Unity公式マニュアル - RigidBody
https://docs.unity3d.com/ja/current/Manual/class-Rigidbody.html

## 11. `OnCollisionEnter` って何？([#19](https://dotinstall.com/lessons/basic_unity_v2/47319))

```C#:BallScript.cs
private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("Paddle"))
    {
        Destroy(gameObject);
    }
}
```

`OnCollisionEnter` はこのスクリプトに紐づけられた GameObject が他のオブジェクトと衝突した場合に実行されるメソッドです。（ RigidBody コンポーネントが追加されている必要があります）



`MonoBehaviour` のスクリプトリファレンスを見てみると「メッセージ」の欄に `OnCollisionEnter` が記載されています。

`MonoBehaviour` クラスのスクリプトリファレンス
https://docs.unity3d.com/ja/current/ScriptReference/MonoBehaviour.html


そこをクリックして `OnCollisionEnter` のリファレンスを見てみると、パラメータ（引数）として `Collision` という型のデータを受け取ることが分かります。

さらに `Collision` をクリックして `Collision` クラスのリファレンスに移動すると、 `Collision` クラスは衝突した相手のオブジェクトや、衝突時のスピードなどの情報をまとめたクラスだということが分かります。

このようにして、はじめて使うクラスやメソッドが出てきた時は、スクリプトリファレンスをたどって読んでいくと理解が深まると思います。


# 最後に

ドットインストールのUnity入門をやって、ある程度Unityの雰囲気が分かった後は、Qiitaにある以下の素晴らしい入門記事を読むと良いと思います。

[UnityをC#で超入門してみる #0　超目次](https://qiita.com/hiroyuki_hon/items/c4da01e1c94bbba2c071)