Unityでテキストデータからゲームステージを作成する


[前回](http://qiita.com/mokemokechicken/items/d5c06f43e8168cff5225) の続きです。

今までは、UnityのUIでステージを構成していましたが、スクリプトを使ってテキストデータからステージを作成するようにします。
こうすると簡単にステージを増やしていくことが可能になります。

必要なものをPrefab化しておく
====

まず、今まで作っていたGameObjectをPrefab化しておきます。
Prefab化しておくと、他のSceneでも簡単に使うことができます。

BarやLadderやBlockは既にPrefab化済みなので、以下のものを忘れずにPrefab化します。

* DirectionLight
* Main Camera
* unityChan

Hierarchy から Project→Assets→Prefab に ドラッグアンドドロップします。
名前は ○○Prefab とかにします。


新しいSceneを作成する
=====

今までのSceneはもうしばらく開発用に使うので、今まで使っていたサンプル用のSceneとは別に、新しいSceneを作成します。
UnityではSceneは大きな区切りで、全GameObjectがリセットされます（させないようにもできるようです）。

Scene作成
----

メニューから [File] -> [New Scene] を選びます。名前を Stage としておきます。
Prefabから Directional Light を設置しておきます。これもスクリプトで設置できますが、どうせ固定なので最初に設置してしまいます。

Stage作成用のScriptを作る
====

空のGame Objectを作って、Scriptを登録する
---
GameObject -> Empty Object で 何も表示されない Game Objectを作ります。
ここにScriptをComponentとして登録します。

そのGameObjectの `Add Component` から Script を選択して StageController.cs を作成して登録します。

StageController.cs
----------

ポイントは以下のことでしょうか。

### PrefabのInstance化

PrefabからGameObjectをScriptで作成するには `Instantiate`を使います。
ステージデータの記号に応じて、対応するPrefabを対応する座標に設置すればOKです。

```
var instance = (GameObject)Instantiate(obj, new Vector3(x, y, 0), Quaternion.identity);
```

実際のPrefabは public field にしておいて、GUIから設定してもらうことにしておきます。
この辺とても便利で良いですね。

### Camera Objectの Targetを設定

Main Camera object は、Targetを追い回すようになっているため、Targetを指定してあげないといけません。
指定したいのは UnityChanの座標なので、UnityChanのObjetを画面生成時に保持しておいて、
後からMain Cameraのtarget field に設定しています。まあ一応動くのでこれでよしとします。


Scriptは以下のようになりました。


```csharp:StageController.cs
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public class StageController : MonoBehaviour {
	public GameObject blockPrefab;
	public GameObject ladderPrefab;
	public GameObject barPrefab;
	public GameObject playerPrefab;
	public GameObject cameraPrefab;

	const char BLOCK = '#';
	const char LADDER = 'H';
	const char BAR = '-';
	const char PLAYER = 'P';

	private GameObject playerObject;

	private Dictionary<char, GameObject> prefabMap;

	// Use this for initialization
	void Start () {
		prefabMap = new Dictionary<char, GameObject> {
			{BLOCK, blockPrefab},
			{LADDER, ladderPrefab},
			{BAR, barPrefab},
			{PLAYER, playerPrefab},
		};

		BuildStage(STAGE_DATA);
		if (playerObject) {
			var camera = (GameObject)Instantiate(cameraPrefab);
			var cameraScript = camera.GetComponent<Camera>();
			cameraScript.target = playerObject.transform;
		}

	}

	void BuildStage(string stageData) {
		// Left Botton's position is (0,0)
		var lines = stageData.Split('\n');
		int y = lines.Count();
		foreach (var line in lines) {
			y--;
			int x = 0;
			foreach (var ch in line) {
				GameObject obj;
				prefabMap.TryGetValue(ch, out obj);
				if (obj) {
					var instance = (GameObject)Instantiate(obj, new Vector3(x, y, 0), Quaternion.identity);
					if (ch == PLAYER) {
						playerObject = instance;
					}
				}
				x++;
			}
		}
	}
	

	const string STAGE_DATA = @"
#         H    #
# P       H    #
#         H    #
#  #HHHHHHH    #
#         H    #
#---------H    #
#         H    #
####H###########
#   H--------- #
#   H          #
#   H ####     #
#   H----      #
#   H    ##### #
#   H          #
#   H          #
################";
}

```



StageControllerスクリプトにPrefabを関連付け
----------------

StageController.cs の Prefab Field に 目的にあった Prefabをドラッグ・アンド・ドロップなどで登録していきます。

![Stage_unity_-_RoadRunner_-_Web_Player_と_テキストデータからゲームステージを作成する_と_Assembly-CSharp_-_Script_StageController_cs_-_MonoDevelop-Unity_と_ターミナル_—_screen_—_130×36.png](https://qiita-image-store.s3.amazonaws.com/0/11124/c34e8751-8080-f1a7-e801-e7a8a8dd7b72.png "Stage_unity_-_RoadRunner_-_Web_Player_と_テキストデータからゲームステージを作成する_と_Assembly-CSharp_-_Script_StageController_cs_-_MonoDevelop-Unity_と_ターミナル_—_screen_—_130×36.png")

他微調整
------

カメラが近すぎて全体が見えなかったので、Main Camera の 'Field of View' を 60 → 100 に変更しました。

![Stage_unity_-_RoadRunner_-_Web_Player.png](https://qiita-image-store.s3.amazonaws.com/0/11124/9e22a1a6-2d2a-9ff3-4041-03b0a16b4129.png "Stage_unity_-_RoadRunner_-_Web_Player.png")


Unityちゃんがだいぶ小さくなって少し寂しいですが、まあ仕方ないかな。。。

おわりに
=====


* 今回のバージョンのWebPlayer版
	* https://dl.dropboxusercontent.com/u/21300511/UnityRoadRunner/demo1g/demo1g.html
* ソースコード
	* https://github.com/mokemokechicken/UnityChanRoadRunner/tree/demo1g