Unity5 3D の的当てゲームにおける投射物の作成

[Unity5の教科書](http://www.sbcr.jp/products/4797386790.html)  「Chapter7 3Dゲームの作り方」で 3D の的当てゲームを作成しましたので、内容をまとめてみました。
3D ゲームならではのポイントも含まれるかと思います。

本文内に登場するコードはすべて C# です。

## Rigidbody

まず、投射物となるオブジェクトに `Rigidbody` コンポーネントをアタッチしておきます。
`Rigidbody` をアタッチすることで、オブジェクトに重力や摩擦などの物理法則にもとづいた挙動をさせることができます。

https://docs.unity3d.com/550/Documentation/ScriptReference/Rigidbody.html

## 投射物を投げる

画面をタッチすると投射物が投げられるというような動作にします。
ここで必要な処理は次の 2 つになるかと思います。

- 画面をタッチしたタイミングで投射物となるオブジェクトを生成する
- 生成したオブジェクトを飛ばす

### 画面をタッチしたタイミングで投射物となるオブジェクトを生成する

投射物となるオブジェクト(ここでは `projectile` とします)は 1 つではなく、プレイヤーが画面をタッチするのにあわせて生成されます。
そのため Prefab を利用してゲーム内で生成するようにします。

Prefab を利用するメリットなどは以下の記事に書いていますので、あわせて参考にしていただければと思います。

- http://qiita.com/shiimaxx/items/8b7a51d2d6f36062941a#%E9%9A%9C%E5%AE%B3%E7%89%A9%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B

`projectile` を生成するスクリプトは次のとおりです。

```C#
public GameObject projectilePrefab;

void Update () {
	if (Input.GetMouseButtonDown (0)) {
		GameObject projectile = Instantiate (projectilePrefab) as GameObject;
    }
```

- `public GameObject projectilePrefab;`
    - `projectile` の Prefab を格納するための変数を宣言しています
- `if (Input.GetMouseButtonDown (0))`
    - 画面がタッチされたことを判定するために if 文を利用します
- `GameObject projectile = Instantiate (projectilePrefab) as GameObject;`
    - `projectilePrefab` をもとに `projectile` を生成します
    - 上記の if 文の中にある処理なので、画面をタッチすると `projectile` が生成されるようになっています


### 生成したオブジェクトを飛ばす

`projectile` には `Rigidbody` がアタッチされていますので、`Rigidbody.AddForce` を使ってオブジェクトを飛ばすようにしてみます。
`Rigidbody.AddForce` は引数に x, y z 座標で力のベクトルを指定して与えることで、任意の方向にオブジェクトを動かすことができます。

- 公式ドキュメント
    - https://docs.unity3d.com/ja/540/ScriptReference/Rigidbody.AddForce.html

スクリプトは次のとおりです。

```C#
void Update () {
    :
    projectile.GetComponent<Rigidbody> ().AddForce (new Vector3 (0, 200, 2000));
```

x, y, z 座標を指定した `Vector3` 型のオブジェクトを引数として渡しています。
z 軸に 2000 の力でオブジェクトが飛んでいくようになります。またオブジェクトが重力で落ちるスピードを和らげるために、y 軸にも 200 の力をかけています。

## 画面をタッチした方向に投射物を投げる

これまでの内容で、画面をタッチすると投射物が投げられるという実装ができました。
ただ、現状では画面をタッチした場所に関わらず、投射物は固定方向にしか飛びません。
投射物が画面をタッチした方向に飛ぶようにしてみたいと思います。

画面をタッチした場所の座標の取得には `Input.mousePosition` を利用します。
また、 `Input.mousePosition` を `Camera.ScreenPointToRay` の引数とすることでタッチした場所にもとづいた Ray を返すようにできます。

- https://docs.unity3d.com/ScriptReference/Camera.ScreenPointToRay.html

Ray は名前のとおり光線を表現することができる構造体です。

- https://docs.unity3d.com/550/Documentation/ScriptReference/Ray.html

スクリプトは次のとおりです。

```C#
void Update () {
    :
    Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
    Vector3 direction = ray.direction;
    projectile.GetComponent<Rigidbody> ().AddForce (direction.normalized * 2000);
```

- `Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);`
    - タッチした場所をあらわす `Input.mousePosition` を引数として `Camera.ScreenPointToRay` を実行することで、タッチされた方向にむかうベクトルを取得します
- `Vector3 direction = ray.direction;;`
    - `ray.direction` を `direction` に代入します
    - `ray.direction` は Ray であらわされる光線の方向にあたる `Vector3` 型のオブジェクトです
- `projectile.GetComponent<Rigidbody> ().AddForce (direction.normalized * 2000);`
    - `direction.normalized` でベクトルの正規化をおこない、長さ「1」のベクトルとしたあとに 2000 の力がかかるようにします
        - https://docs.unity3d.com/jp/540/ScriptReference/Vector3-normalized.html

## 参考文献

- [Unity5の教科書](http://www.sbcr.jp/products/4797386790.html)
- https://docs.unity3d.com/550/Documentation/ScriptReference/Rigidbody.html
- https://docs.unity3d.com/550/Documentation/ScriptReference/Rigidbody.AddForce.html
- https://docs.unity3d.com/550/Documentation/ScriptReference/Camera.ScreenPointToRay.html
- https://docs.unity3d.com/550/Documentation/ScriptReference/Ray.html
- https://docs.unity3d.com/550/Documentation/ScriptReference/Vector3-normalized.html
- http://qiita.com/shiimaxx/items/8b7a51d2d6f36062941a