Unityちゃんがステージ上のブロックと正しく干渉するようにする


はじめに
======

[前回](http://qiita.com/mokemokechicken/items/137c3a00d44841d3473e) に続きまして、
今回は「ロードランナー風」のゲームを作るためのステージ上のブロックを作り、
その辺りをUnityちゃんが動くようにします。

やりたいこと
--------------
基本的には、以下のことができればOKとします。

* 足元にBlockがなければ落ちる
* 左右にBlockがあれば進めない

準備
=======

その前に少し下記の準備をします。

* Blockを作ってステージに並べる
* Unityちゃんを左右にしか動かないようにする
* カメラを追随させる

Blockを作ってステージに並べる
------------------

### Blockを作る
[GameObject] -> [Create Other] -> [Cube] を選びます。
すると真っ白い四角が出現します。

大きさが (1,1,1) になっていると思いますが好都合です。この大きさを今回の基本単位にしようと思います。
Unityでは、この 大きさ1 が 1メートル を意味しています(物理演算の重力値が9.8なので)。Unityちゃんも1.6くらいの大きさですしね。

白だと少し違和感があるので、色を付けておきます。
色やテクスチャを設定するには material というのを使います。

### materialの作成と付加
Project メニューから [Create] -> [Material] を選びます。Inspectorから下図の部分をクリックして、適当な色を選びます。

![demo1_unity_-_RoadRunner_-_Web_Player_と_Unityちゃんがステージ上のブロックと正しく干渉するようにする.png](https://qiita-image-store.s3.amazonaws.com/0/11124/1f07dd59-ef7c-1bfd-1ba5-dcb07ad678a5.png "demo1_unity_-_RoadRunner_-_Web_Player_と_Unityちゃんがステージ上のブロックと正しく干渉するようにする.png")

そして、先ほど作ったBlockにこのmaterialを紐付ければOKです。
Blockの色が変わったと思います。

### Prefab化する

Prefabというのは同じ種類のGameObjectをたくさん作るときに便利です。
オブジェクト指向言語で言う「Class」みたいなものでしょうか。現実で言う「ハンコ」みたいなものです。
Prefab化しておくと、同じようなObjectが大量に作れるわけです。

作り方は簡単で、作ったBlockをProjectWindowにD&Dします。すると、もとのBlockが青の文字に変わります。これがPrefabから作られたという印になります。
![demo1_unity_-_RoadRunner_-_Web_Player.png](https://qiita-image-store.s3.amazonaws.com/0/11124/a915ae27-4867-2417-345f-95f3884847ef.png "demo1_unity_-_RoadRunner_-_Web_Player.png")

### Blockを並べる

適当で良いですが、以下のように並べてみました。
![demo1_unity_-_RoadRunner_-_Web_Player.png](https://qiita-image-store.s3.amazonaws.com/0/11124/cd1de0bd-d506-346e-485b-8028b458e7ed.png "demo1_unity_-_RoadRunner_-_Web_Player.png")
一括選択してコピー＆ペーストとかでも増やせるので便利です。

Unityちゃんを左右にしか動かないようにする
------------------

今回は奥行きのない2次元的なゲームにしようと思っています。
なのでまずはとりあえず、

* 左キーで左に動く
* 右キーで右に動く

というようにします。

前回作った`UnityChanDemo1` Classの Updateを以下のように書き換えます。

```csharp:UnityChanDemo1
	// Update is called once per frame
	void Update () {
		if (Input.GetKey("right")) {
			transform.position += new Vector3(0.05f, 0, 0);
			transform.rotation = Quaternion.Euler(new Vector3(0, 90, 0));
			animator.SetBool("is_running", true);
		} else if (Input.GetKey ("left")) {
			transform.position += new Vector3(-0.05f, 0, 0);
			transform.rotation = Quaternion.Euler(new Vector3(0, -90, 0));
			animator.SetBool("is_running", true);
		} else {
			animator.SetBool("is_running", false);
		}
	}
```

これで左右にだけ動くようになりました。

`Quaternion` というのが出てきました。が、私自身あまりよくわかっていません（ぐーぐる先生は結構丁寧に教えてくれます）。まあ、適当にやっていたらこれで思うように向きが変わるようになったので、現状ではこれでよしとしておきます。

カメラを追随させる
------------------

今度はUnityちゃんがカメラの外側に出てしまうようになりましたので、カメラをUnityちゃんの動きに合わせようと思います。

`Camera` という C# ファイルを作成します。以下のように書きます。

```cs:Camera
using UnityEngine;
using System.Collections;

public class Camera : MonoBehaviour {
	public Transform target;

	// Use this for initialization
	void Start () {
		target = GameObject.FindWithTag("Player").transform;
	}
	
	// Update is called once per frame
	void Update () {
		transform.position = target.position + new Vector3(0, 1, -3);
	}
}
```

このスクリプトで、`target`の位置をカメラが追います。
`GameObject.FindWithTag` というのを使うと、Tagが付いたObjectを取得することができます。

Tagを付けるには、Unityちゃんを選択してInspectorの下記の部分から選択します。

![demo1_unity_-_RoadRunner_-_Web_Player.png](https://qiita-image-store.s3.amazonaws.com/0/11124/b086a40b-2f0f-eadf-55ef-6b63dd1842e9.png "demo1_unity_-_RoadRunner_-_Web_Player.png")

そして、このスクリプトを Main Cameraに付けておけばOKです。

UnityちゃんとBlockの相互作用の設定
==========

せっかくなので、Unityの物理演算や衝突判定を使って、Blockの上を歩いたり落ちたりするようにします。

UnityちゃんにColliderを設定
--------
Colliderはおおよそ「衝突判定の範囲」を表します。

Unityちゃんを選択してから、[Add Component]を選んで、[Physics] -> [Capusel Collider]を選択します。
![demo1_unity_-_RoadRunner_-_Web_Player_と_Unityちゃんがステージ上のブロックと正しく干渉するようにする（準備編）.png](https://qiita-image-store.s3.amazonaws.com/0/11124/eb26639d-1989-7401-4ee9-560aa7e45103.png "demo1_unity_-_RoadRunner_-_Web_Player_と_Unityちゃんがステージ上のブロックと正しく干渉するようにする（準備編）.png")
この範囲がUnityちゃんの体の輪郭とだいたいFitするように数字を調整します。今回は上図のように設定します。

UnityちゃんにRigidbodyを設定
--------
Rigidbodyは物理演算を使って、落ちたり、他のモノと干渉したりするときに付けます。この辺いつも手探りでやっているのですが、まあ、だいたい上手く動いているのでよしとします。

[Add Component]を選んで、[Physics] -> [Rigidbody]を選びます。
するとComponentが追加されるので以下のように設定します。

![demo1_unity_-_RoadRunner_-_Web_Player_と_Unityちゃんがステージ上のブロックと正しく干渉するようにする（準備編）.png](https://qiita-image-store.s3.amazonaws.com/0/11124/52bbd488-89d8-c412-c84a-c877ecdba2d8.png "demo1_unity_-_RoadRunner_-_Web_Player_と_Unityちゃんがステージ上のブロックと正しく干渉するようにする（準備編）.png")

ポイントは以下の設定でしょうか。

* Use Gravity: 重力の影響を受けるか → Yesとする
* is Kinematic: 物理演算で動かないObjectにする → Noとする
* Freeze Position: ZのみOn → 奥に勝手に移動しないようにするため
* Freeze Rotation: 全てON → 勝手に物理演算でこけたりしないように

いろいろ変更してみると面白いと思います。

実行してみる
=====

Unityちゃんを適当な位置においてゲームを開始すると、ちゃんと落ちてBlockのところで止まったりするようになると思います。

![demo1_unity_-_RoadRunner_-_Web_Player.png](https://qiita-image-store.s3.amazonaws.com/0/11124/fa4fa89b-ed65-9212-cc7c-ddd3fabf10eb.png "demo1_unity_-_RoadRunner_-_Web_Player.png")