Posted at

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

More than 5 years have passed since last update.

前回 の続きです。

今までは、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は以下のようになりました。


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


他微調整

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

Stage_unity_-_RoadRunner_-_Web_Player.png

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


おわりに