パート③:ランダムに配置される物体(アイテム・内壁)を配置する@2Dローグライク公式tutorial解説【Unity2018】

このパートで行うこと

前回まででフィールド内の決まった位置に配置される床・外壁・出口を作り終わった。
このパートでは、ランダムな位置に配置されるアイテムと内壁の配置を行う。
今回は新しい内容はランダムな配置をする部分のみなのでサクッと進めてしまおう。

f:id:snoopopo:20180704160611p:plain


前回の記事はこちら。
パート②:静的な物体(床・外壁・出口)を配置する@2Dローグライク公式tutorial解説【Unity2018】


※この記事は、unity公式チュートリアル「2D Roguelike tutorial」を解説した連載記事です。
この連載記事共通の事項(実施している環境等)は以下の記事を参照ください。
表紙:2Dローグライク公式tutorial解説【Unity2018】


内壁のプレハブを作成する

まずはじめに内壁のプレハブを作成する。

SortingLayerは、前パートの出口と同様に「Items」とし、床よりも手前に表示させるようにしておく。
新規でゲームオブジェクトを作成しても、今まで作成したプレハブを元にしてもかまわない。
前パートの復習になるが、
SpriteRenderer#SpriteSpriteRenderer#SortingLayer を設定すればよかったことを思い出そう。

プレハブ名 Sprite
Wall1 Scavengers_SpriteSheet_21
Wall2 Scavengers_SpriteSheet_22
Wall3 Scavengers_SpriteSheet_23
Wall4 Scavengers_SpriteSheet_24
Wall5 Scavengers_SpriteSheet_27
Wall6 Scavengers_SpriteSheet_29
Wall7 Scavengers_SpriteSheet_30
Wall8 Scavengers_SpriteSheet_31

アイテムのプレハブを作成する

アイテムのプレハブについても一気に作ってしまおう。 SortingLayerは、「Items」にしておくこと。

プレハブ名 Sprite
Food Scavengers_SpriteSheet_19
Soda Scavengers_SpriteSheet_18

内壁とアイテムを配置する

作成した内壁とアイテムを配置していこう。

内壁とアイテムの数は位置もランダムだが、配置される数もランダムである。
配置数は、最大と最小を決め、その中からランダムな数を決めるようにする。

BoardManager.cs
public class BoardManager : MonoBehaviour {

    [System.Serializable]
    public class Count {
        public int minimum;
        public int maximum;

        public Count(int min, int max) {
            minimum = min;
            maximum = max;
        }
    }

    public int columns = 8;
    public int rows = 8;
    public Count wallCount = new Count(5, 9); //内壁の配置数
    public Count foodCount = new Count(1, 5);  //アイテムの配置数

    public GameObject[] floorTiles; //床プレハブ
    public GameObject[] outerWallTiles; //外壁プレハブ
    public GameObject exit; //出口プレハブ
    public GameObject[] foodTiles; //アイテムプレハブ
    public GameObject[] wallTiles; //内壁プレハブ

    private Transform boardHolder;

    //以下省略 
}

配置数の最小最大の定義のために Count インナークラスを定義した。
クラス定義についている[System.Serializable] はインスペクターで設定できるようにするためにつけている。


また、上記のコードで アイテムのプレハブと内壁のプレハブを設定するフィールドを追加しているので インスペクターで設定を行なってしまおう。

f:id:snoopopo:20180704122635p:plain


アイテムと内壁はランダムな位置に配置されるが、
プレイヤーが出口までいく道すじが内壁でなくなってしまう可能性があるので、
プレイヤーが動き回れるエリアの内周1マス分にはアイテムも内壁も配置しないようにする。
よってアイテムと内壁を配置エリアは以下のようになる。

f:id:snoopopo:20180704161630p:plain

まずはこのランダム配置可能な位置リストを取得するメソッド InitialiseList()作成する。

BoardManager.cs
using  System.Collections.Generic; //忘れずに追加すること!!

// 〜省略〜

private List<Vector3> gridPositions = new List<Vector3>(); //ランダム配置可能な位置リスト

void InitialiseList() {
    gridPositions.Clear();
    for (int x = 1; x < columns - 1; x++) {
        for (int y = 1; y < rows - 1; y++) {
            gridPositions.Add(new Vector3(x, y, 0f));
        }
    }
}

ランダム配置可能なエリアは(1,1)~(6,6)の範囲なので上記のfor文となる。

このゲームは2DなのでVector3のzは0fにしている。

SetupScene()InitialiseList()を呼び出すようにしておこう。

BoardManager.cs
public void SetupScene() {

    //外壁と床配置
    BoardSetup();

    //ランダム配置できる位置リストを取得
    InitialiseList();

    //出口配置
    Instantiate(exit, new Vector3(columns - 1, rows - 1, 0f), Quaternion.identity);
}

次に先ほど取得したランダム配置できる位置リストから、ランダムな位置を返すメソッドを作成する。

BoardManager.cs
Vector3 RandomPosition() {
    int randomIndex = Random.Range(0, gridPositions.Count);
    Vector3 randomPosition = gridPositions[randomIndex];
    gridPositions.RemoveAt(randomIndex);

    return randomPosition;
}

最後にランダムで決めた配置数分、今作成したRandomPosition()を使って取得したランダムな位置に配置を行う LayoutObjectAtRandom()を作成する。

引数のprefabArrayは複数種類作成したアイテムや内壁のプレハブのリストだ。

BoardManager.cs
void LayoutObjectAtRandom(GameObject[] prefabArray, int minimum, int maximum) {
    //配置数を決める
    int objectCount = Random.Range(minimum, maximum + 1);

    for (int i = 0; i < objectCount; i++) {
        Vector3 randomPosition = RandomPosition(); //配置する位置を取得
        GameObject prefabChoice = prefabArray[Random.Range(0, prefabArray.Length)];
        Instantiate(prefabChoice , randomPosition, Quaternion.identity);
    }
}

Random#Range()は第二引数のmax-1までの値しか返さない。
今回作った、Count#maximumの値はランダムで生成される値に含んでほしいため、+1した値を渡している。


アイテムと内壁の配置を行おう。残りの作業は、 SetupScene()LayoutObjectAtRandom()を呼び出すだけだ。

public void SetupScene() {

    //外壁と床配置
    BoardSetup();

    //ランダム配置できる位置リストを取得
    InitialiseList();

    //出口配置
    Instantiate(exit, new Vector3(columns - 1, rows - 1, 0f), Quaternion.identity);

    //内壁配置
    LayoutObjectAtRandom(wallTiles, wallCount.minimum, wallCount.maximum);

    //アイテム配置
    LayoutObjectAtRandom(foodTiles, foodCount.minimum, foodCount.maximum);

}

ゲームを何度か起動して確認してみよう。
起動のたびにアイテムと内壁の位置や配置数が変わっているはずだ。

f:id:snoopopo:20180704160611p:plain

次回予告

このパートまでで、計5種類の物体の配置が完了した。 いよいよ次からはプレイヤーを作っていき、プレイヤーを動かせるようにする。一層ゲームらしくなるはずだ。

⇒ 続きのパートはこちら。

www.snoopopo.com