Unity でローグライクゲームを作ってみよう(マップオブジェクト化編)

なかなかやる気が出ずに放置して早1年が過ぎましたが、なんとなくアクセス解析をしてみるとどうやら前回(マップ自動生成編)
このブログで1番の人気記事だったようです。

せっかく皆さんにアクセス頂いているので、続きをやろうと思います。
今回は「タップした場所にキャラクターを移動させる」と予告していました。
が、その前にマップがまだオブジェクト化されていないので先にそちらからやっていきましょう。

ソースコードは kurage1119/sample-unity-roguelike にアップしてあるので、落としておいて頂けるとこの先の説明が分かりやすいかと思います。

マップオブジェクトの配置

前回は 0 と 1 の配列でマップを作っただけなので、まずはそれをオブジェクトしてシーン上に配置する必要があります。

「0 を壁、1 を床」として作っていたので、まずはそれに合わせて Cube (壁) と Plane (床) を配置していきます。

一度 Cube と Plane をシーン上に追加し、ドラッグアンドドロップでPrefab 化します。
Prefab のパスは「Resources/Prefabs/Wall (Floor)」としました。
Plane はそのままだと大きいので、Scale の値をすべて「0.1」にしてサイズを調整しておいてください。


※視覚的に分かりやすいよう床の方に適当な色をつけておきました。

では、今作った Prefeb を使ってさっそくマップを可視化しましょう。

シーンに「Initializer」という名前で新規の GameObject を追加します。

追加したら Initializer に「Scripts」フォルダに入っている「SceneInitializer」をアタッチしてください。

このスクリプトは、前回作ったマップ自動生成の結果を 01 の配列で受け取り、0 なら壁(Wall)を、1 なら床(Floor)を Instantiate する処理が書かれています。

private void GenerateMap() {
    map = new MapGenerator().GenerateMap(MAP_SIZE_X, MAP_SIZE_Y, MAX_ROOM_NUMBER);

    for (int y = 0; y < MAP_SIZE_Y; y++) {
        for (int x = 0; x < MAP_SIZE_X; x++) {
            if (map[x, y] == 1) {
                Instantiate(floorPrefab, new Vector3(x, 0, y), new Quaternion());
            } else {
                Instantiate(wallPrefab, new Vector3(x, 0, y), new Quaternion());
            }
        }
    }

}

この状態でシーンを再生すると・・・

こんな感じでそれっぽいのが表示されるかと思います。
たまに通路の先の部屋がなかったり、部屋が異様に偏ったりしてしまうことがありますが、ご愛敬ということで無視してください。
そのうち気が向いたら修正しておきます。

困ったときは「Scenes」フォルダに入っているシーンファイル(create_map)を開けばここまでの状況を再現できます。

キャラクターの配置

マップオブジェクトが生成できるようになったので、次は操作用のキャラクターを配置していきます。
キャラクターにはお馴染みユニティちゃんをお借りします。

公式 からユニティちゃんのモデルデータをダウンロードしてサクっとインポートしてください。
とりあえずはそのまま全部インポートしましょう。

インポートできたらユニティちゃんのモデルをシーン上にドラッグアンドドロップしてシーンに登場させましょう。

さらに、先ほど追加した Initializer の Scene Initializer スクリプトの Player プロパティにユニティちゃんを追加します。

このスクリプトには先ほどのマップオブジェクト化に加えて、Player に設定した GameObject をランダムな位置に再配置する処理が書かれています。
もちろん、壁の中に移動することがないよう制御しています。

private void SponePlayer() {
    if (!_player) {
        return;
    }

    Position position;
    do {
        var x = RogueUtils.GetRandomInt(0,  MAP_SIZE_X - 1);
        var y = RogueUtils.GetRandomInt(0,  MAP_SIZE_Y - 1);
        position = new Position(x, y);
    } while (map[position.X, position.Y] != 1);

    _player.transform.position = new Vector3(position.X, 0, position.Y);
}

ここまで設定したらもう一度シーンを再生してみましょう。

オブジェクト化されたマップのどこか床の上にユニティちゃんがいるはずです。

ここまでくれば次はこのユニティちゃんをタップした場所に動かせばいいですね。

ここまでの進捗

マップがオブジェクトとしてシーン上に生成され、操作キャラクターとなるユニティちゃんがスポーンしました。
「Scenes」フォルダに入っている「spone_unity_chan」を開けば今回の最後の状態が再現できます。

また、このプロジェクトは GitHub 上で公開しているので、興味があればぜひ落としてみてください。
kurage1119/sample-unity-roguelike
次回こそは「タップした場所にキャラクターを移動させる」をやってみたいと思います。

それでは。