unityで自動マップ生成システムを作ろう!

unity

今日はunityで3Dランゲームなどで使える自動生成システムを作っていきたいと思います。この自動生成システムで障害物などを流すだけで疑似ランダム自動マップ生成ができます。

完成イメージ

・木や石が流れてくる(見方を変えれば自分が走ってるように見える)

・種類や間隔を自分で変更できる

・終了時間の設定ができる

障害物とジェネレータを用意する

今回は障害物4種類用意しました。右図はそのうちの一つの木です。

is Kinematicをoffにするのと、rigidboyのrotationのxとzを固定しないと動かなかったり干渉したり、回転しちゃったりします。

このようにできたらドラック&ドロップでprefab化。

続いてはジェネレータ。これも簡単に流れてきてほしいところに設置します。今回は-z方向に流すためz=0のところに設置しました。この後書くコードを後でアタッチします。

ジェネレータのコードを書く

続いてジェネレータのコードを書いていきます。詳細はコード中にコメントしました。

重くならない様に自動破壊の処理や、終了時間の設定、流れる速度、生成密度(頻度?)をInspectorから設定できるようにしました。

using UnityEngine;

public class EnvronmentGenerator : MonoBehaviour
{
    public GameObject[] obstaclePrefabs; // 生成する障害物のプレハブ
    public float destroyZPosition = -20f; // 自動破壊のZ位置
    public float totalTime = 60f; // 終了までの時間
    public float obstacleSpeed = 5f; // 障害物の速度
    public float spawnDensity = 1f; // 生成密度
    public Vector3 spawnAreaSize = new Vector3(9f, 1f, 1f); // 生成エリアのサイズ

    private float elapsedTime = 0f;

    private void Update()
    {
        elapsedTime += Time.deltaTime;

        // 経過時間が総時間を超えたら終了
        if (elapsedTime >= totalTime)
        {
            Destroy(this.gameObject);
            return;
        }

        // 生成密度に応じて障害物を生成
        if (Random.value < spawnDensity * Time.deltaTime)
        {
            SpawnObstacle();
        }
    }

    private void SpawnObstacle()
    {
        // ランダムなプレハブを選択
        GameObject obstaclePrefab = obstaclePrefabs[Random.Range(0, obstaclePrefabs.Length)];

        // ランダムな位置を生成エリア内から選択
        Vector3 spawnPosition = transform.position + new Vector3(Random.Range(-spawnAreaSize.x / 2f, spawnAreaSize.x / 2f), 0f, Random.Range(-spawnAreaSize.z / 2f, spawnAreaSize.z / 2f));

        // プレハブから障害物を生成
        GameObject obstacle = Instantiate(obstaclePrefab, spawnPosition, Quaternion.identity);

        // 障害物に速度を与える(Z軸の正の方向に進む)
        Rigidbody obstacleRb = obstacle.GetComponent<Rigidbody>();
        if (obstacleRb != null)
        {
            obstacleRb.velocity = Vector3.forward * obstacleSpeed*-1.0f;//-1.0fは-方向へ流すため。
        }


        // 一定のZ位置に到達したら自動で破壊
        Destroy(obstacle, (spawnPosition.z - destroyZPosition) / obstacleSpeed);
    }
}

これをアタッチしたら次のように流したい障害物をObstacle prefabsに入れて、準備完了です。

流し始める位置だけ気を付けてください。今回のコードは-z方向に流れていきます。ここはご自分の流したい方向に合わせてください。

これで3Drunゲーム風の疑似ランダムマップ生成ができますね!

コメントを残す コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

コメント

タイトルとURLをコピーしました