Categories: Unity

Unity:リプレイの度にオブジェクトをランダムな位置に発生させる

今回はアイテム探しを行うゲームを作成する場合などに必要な仕掛けとして、ゲームをリプレイする度にアイテムの場所がランダムに発生する仕組みを試してみました。

シーンの作成

基本オブジェクト Plane を配置。その上にオブジェクトの生成位置として基本オブジェクト Cube を配置。
名前は Spawn Point に変更してプレハブに変換。複製して9個配置しました。

生成位置のプレハブ Spawn Point はデフォルトで用意されているタグ Respawn を設定。

生成するゲームオブジェクトは基本オブジェクト Sphere を使用してプレハブに変換しておきます。

シーンのリロード

まずはUIボタンをクリックするとシーンをリロードする仕組みを作ります。

UIオブジェクトの作成

シーンをリロードするためのUIボタン Button Replay を作成し、ゲーム画面の右下に配置しました。

スクリプトの作成と編集

UIボタン Button Replay をクリックしたら実行されるスクリプトを作成します。
[Hierarchy]ウィンドウ > Canvas を選択。[Inspector]ウィンドウ > [Add Component]ボタン > New Script を選択。
Nameフィールドに SceneReload を入力して[Create and Add]ボタンをクリック。

完成したスクリプトはこのようになりました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneReload : MonoBehaviour
{
    // シーンのリロード(UIボタンクリックで呼び出す処理)
    public void LoadScene()
    {
        // 現在のシーンを取得して変数 scene に格納
        Scene scene = SceneManager.GetActiveScene();
        // シーンをロードする
        // 引数でシーン名の指定:変数 sceneに格納されたシーン名 scene.name
        SceneManager.LoadScene(scene.name);
    }
}

現在のシーンを GetActiveScene() で取得して変数 scene に格納。シーンをロードする SceneManager.LoadScene の引数 (scene.name) でシーン名を参照しています。

コンポーネントの設定

UIボタン Button Replay を選択して[Inspector]ウィンドウ > Button (Script) > On Click() 処理のオブジェクトフィールドに [Hierarchy]ウィンドウ > Canvas をドラッグ&ドロップで割り当て。実行する処理は SceneReload > LoadScene を選択します。

オブジェクトの生成位置をランダムに設定

次に、シーンをリロードする度に異なる位置にオブジェクトが生成される仕組みを作成します。

オブジェクトとスクリプトの作成

ランダム位置に生成するスクリプトを割り当てるためのオブジェクトを作成します。
[Hierarchy]ウィンドウ > [Create] > Create Empty を選択。名前を Spawner に変更。

[Inspector]ウィンドウ > [Add Component]ボタン > New Script を選択。
Nameフィールドに RandomSpawner を入力して[Create and Add]ボタンをクリック。

スクリプトの編集

シーンが切り替わっても変数の値を保持するために、生成オブジェクトの位置と比較用の変数に public static を定義しています。
完成したスクリプトはこちらのようになっています。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RandomSpawner : MonoBehaviour
{
    // オブジェクトを格納する変数
    public GameObject respawnPrefab;
    // オブジェクトの生成位置を格納する配列
    private GameObject[] spawnPoints;
    // オブジェクトの生成位置を格納する変数
    //(シーン間で受け渡しをするので public static を定義)
    public static Vector3 spawnPoint;
    // 前回のシーンで生成したオブジェクトの生成位置を格納する変数
    // シーンをリロードした際にオブジェクトの生成位置が前回のシーンと同じか比較するための変数
    //(シーン間で受け渡しをするので public static を定義)
    public static Vector3 RespawnPoint;

    // ゲームの初期化
    void Start()
    {
        // タグ Respawn が設定されたオブジェクトを配列 spawnPoints に格納する
        spawnPoints = GameObject.FindGameObjectsWithTag("Respawn");

        // 配列 spawnPoints が空でなく 0 より大きい場合
        if (spawnPoints != null && spawnPoints.Length > 0)
        {
            // オブジェクトの生成位置が前回のシーンと同じ場合は処理を繰り返す
            while (spawnPoint == RespawnPoint)
            {
                // 配列 spawnPoints からランダムに 1 つ抽出し、
                // コンポーネント transform.position の値を spawnPoint に渡す
                spawnPoint = spawnPoints[Random.Range(0, spawnPoints.Length)].transform.position;
            }
            // オブジェクトをシーンに生成
            // 変数 respawnPrefab に格納されたオブジェクトを 変数 spawnPoint の位置に生成
            Instantiate(respawnPrefab, spawnPoint, transform.rotation);
            // オブジェクトの生成位置を比較用の変数に格納する
            RespawnPoint = spawnPoint;
        }
    }
}

配列にオブジェクトを格納してランダムに取り出す処理は、Unityの公式チュートリアル「マルチプレイヤーネットワーキング」生成と再生成 の記事で掲載されているスクリプトを参考にしました。

コンポーネントの設定

オブジェクト Spawner を選択。[Inspector]ウィンドウ > RandomSpawner (Script) > respawnPrefab フィールドにプレハブ Sphere を割り当て。これで完成です。

WebGL

完成したシーンをWebGL でビルドしました。 Replay ボタンをクリックする度に、シーンがリロードされて青い球が異なる位置に生成されます。
画像クリックでゲーム実行(ファイルサイズ:約10MB)

corevale