前回 の続きです。
今までは、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は以下のようになりました。
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をドラッグ・アンド・ドロップなどで登録していきます。
他微調整
カメラが近すぎて全体が見えなかったので、Main Camera の 'Field of View' を 60 → 100 に変更しました。
Unityちゃんがだいぶ小さくなって少し寂しいですが、まあ仕方ないかな。。。