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

  • 29
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

前回 の続きです。

今までは、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ちゃんがだいぶ小さくなって少し寂しいですが、まあ仕方ないかな。。。

おわりに