doridoridoriand’s diary

主に技術的なことを書いていく予定(たぶん)

Unityで大量のオブジェクトをランダムに生成して更にそれぞれランダムに行動させる

Unityロゴあればいいやと思ってタイトル無しにした笑
それにしてもUnityのDocumentationわかりやすくてよかった

とりあえず空間上に大量の障害物などをまき散らして、 更に自立して行動させたいとかってしたくなると思います。どうやるかちょっと悩んだので備忘録がてら

まず転がしたいプレハブちゃんを用意します。まあ適当に3Dオブジェクトを作りましょう

とりあえずUnity公式のチュートリアルのやつを持ってきました。 ここからプレハブを生成します。まずからのGameObjectをとりあえず新規で追加します

ヒエラルキー(hierarchy)にこんな感じで生成できたと思います↓

次にこの空のオブジェクトに対してmodelから対象となるものを子要素としてアタッチしてあげましょう

選択して…

ドラッグアンドドロップで子要素として追加

で、GameObjectだと普通にわかりづらいので、わかりやすい名前にリネームします。とりあえずRotationRockとでもしておきます

次に、このオブジェクト自身を動かすためのコードを書きます。とりあえず回転させながら適当な方向に運動でもしてもらいましょう

先ほど子要素にしたモデルを選択して、

Inspectorから、[Add Component] -> [New Script] -> 名づけたいクラス名を入力&追加します。とりあえずRotatorとしました

すると、C#ファイルが生成されたかと思います。これを編集していきます。右上のギアアイコンをクリックし、Edit Scriptを選択します

以下のようなコードを書きます

using UnityEngine;
using System.Collections;

public class Rotator : MonoBehaviour {

  // オブジェクト生成時に初速度を与えて等速直線運動をさせる
  void Start() {
    GetComponent<Rigidbody>().velocity = transform.forward;
  }

  // オブジェクトを(x, y, z)すべての成分をランダムにして回転運動をさせる
  void Update() {
    transform.Rotate(new Vector3(Random.Range(0, 180),
                                 Random.Range(0, 180),
                                 Random.Range(0, 180)
                                ) * Time.deltaTime);
  }
}

以上のコードを書き終わったら、子要素にしたモデルのInspectorをから[Add Component] -> [Physics] -> [Rigidbody] を追加してください。これを追加することによって物理的な要素を与えることが出来ます

ここで試しに実行してみましょう

これで1つの時が出来るようになりました。次はこれをランダムに生成しようと思います。ひとまずRotationRockをプレハブとして保持するようにします。
ヒエラルキーに入っているRotationRockをドラッグアンドドロップでAssets/Prefabs配下に持っていきます

次に空のGameoOjectを作成しましょう(Create Emptyです)
とりあえずRocksとでもリネームしましょうか。ここで先ほどのようにInspectorからRigidbodyを追加します。 また、新たにコードが必要になるので適当な名前(個人的にはRandomObjectsとしました)で新規に追加します
Inspectorは以下のようになっているかと思います

ではコードを書いていきましょう。以下のようなコードになります

using UnityEngine;
using System.Collections;

public class RandomObjectGenerator : MonoBehaviour {

  public GameObject targetGameObject;
  public float MinRange, MaxRange;

  // 今はとりあえず決め打ちで500個生成しています
  void Start () {
    for (int i = 0; i <= 500; i++) {
      Instantiate(targetGameObject, new Vector3(Random.Range(MinRange, MaxRange),
            Random.Range(MinRange, MaxRange),
            Random.Range(MinRange, MaxRange)),
            Quaternion.Euler(Random.Range(0, 180),
                             Random.Range(0, 180),
                             Random.Range(0, 180)));
    }
  }
}

Instantiateは、実行時にオブジェクトを複製する関数です。これに対象となるGameObjectと初期座標、初期のオイラー角を入れてあげればランダムに生成されます

ちなみにpublic float MinRange, MaxRangeで初期座標部分に関しての上限値と下限値はInspectorから入力可能にしています

実行してみると次のような結果が得られるかと思います

あまり生成数が多いと重くなるかもしれませんが、普通に面白いので色々試してください
久しぶりにめっちゃ書いたなw