【Unity】Prefabからオブジェクトをたくさん生成するサンプル
UnityではPrefabを用意しておくことで、スクリプトからインスタンス化することができます。ゲーム実行中にたくさんのオブジェクトを生成したい場合はこの機能をマスターしておくと開発が捗ります。
この点については以下の記事で解説を行っています。
このページでは、上で紹介したページでちょっと紹介したたくさんのオブジェクトを生成するサンプルコードを解説付きで紹介します。
こうしたサンプルを通して機能を確認していくことも大切なので、あなたのコーディングの引き出しを充実させる材料になれば嬉しいです。
環境
macOS Catalina 10.15
Unity2019.4.4f1
参考文献
UnityのマニュアルでPrefab(プレハブ)について解説されているのでこちらもご覧ください。
こちらはUnityのスクリプトリファレンスです。Instantiateメソッドの使い方が記載されています。
PrefabをInstantiateする
スクリプトからPrefabをInstantiateする方法については、以下の記事に詳しく記載したのでこちらもぜひ。
空からたくさんのオブジェクトを降らせるサンプル
以下の画像のように、3つの色のCubeがどんどん生成されて、空から落ちてくるサンプルを作成したいと思います。
このサンプルでは以下のことが学べます。
- PrefabをInstantiateする
- 生成したオブジェクトの親オブジェクトを設定する
- 乱数によって処理を分岐させる
- スクリプトからオブジェクトのマテリアルを変更する
- フレームカウントによって処理を分岐する(ちょっと発展)
Cubeを作成
まずはPrefabとして作成する『Cube』オブジェクトを作成します。サンプルでは『Cube』にしていますが、3Dのオブジェクトであれば『Sphere』でも『Capsule』でもOKです。
この『Cube』オブジェクトに『Rigidbody』コンポーネントをアタッチします。設定値はこのままで構いません。あ、緑にしているのはUnityの画面でそう表示されるのではなく、私があとでPhotoshopで色をつけているだけです。念のため。
作成した『Cube』オブジェクトをプロジェクトウィンドウにドラッグ&ドロップします。こうすることでPrefabのアセットファイルが作成されます。Prefabのアセットファイルは任意のフォルダを用意しておくと整理しやすいと思います。
Prefabが作成されると以下のようにアセットファイルが表示されます。
Prefab作成後は、シーンにある『Cube』オブジェクトを削除しておきましょう。ヒエラルキーウィンドウで『Cube』オブジェクトを選択している状態で右クリックまたは二本指タップしてメニューを開き、[Delete] を選択します。
Planeの作成
空から落ちてくる『Cube』を受け止めるオブジェクトとして『Plane』を作成します。ヒエラルキーウィンドウで何も選択していない状態で右クリックまたは二本指タップしてメニューを開き、[3D Object] -> [Plane] を選択します。
作成した『Plane』オブジェクトで『Transform』コンポーネントのScaleを設定します。ここではX, Y, Z全ての項目で [2] を設定しましょう。
マテリアルの作成
続いてマテリアルを作成しましょう。マテリアルもフォルダを作成しておくと便利です。
プロジェクトウィンドウで右クリックまたは二本指タップしてメニューを開き、[Create] -> [Material] を選択します。
作成されたマテリアルの名前を [PrefabCubeCyan] に変更します。ここで設定する名前はあなたが分かりやすいように設定してもらえればOKです。下の画像では、色をシアンにするつもりだったのでCyanの文字を入れています。
インスペクターウィンドウから設定を入れていきましょう。この画像では既に設定を終えていますが、オレンジ色の四角で囲っている部分を設定していきます。
『Main Maps』の項目の中にある『Albedo』で色の部分をクリックするとカラーウィンドウが表示されます。カラーウィンドウでは『Hexadecimal』の項目を [00FFFF] に設定します。あるいは『R』の項目を [0] にする方法でもOKです。
インスペクターウィンドウに戻って『Smoothness』の値を [1] に変更します。ツルツルな感じで表示してみましょう。
さらに『Emission』の項目にチェックを入れて、『Color』の項目でカラーウィンドウを表示します。ここでは『R』の項目に [24] 、『G』の項目に [64] 、『B』の項目に [64] を入力しましょう。
ここで表示されている『HDR』について気になる場合は以下の記事もご参照ください。
インスペクターウィンドウに戻ったら『Global Illumination』の項目で [Realtime] を選択します。これによって、動いているオブジェクトでも光っている感を表現できます。
これでシアンの色のマテリアルは設定が完了しました。プロジェクトウィンドウで『PrefabCubeCyan』を選択して、Windowsなら [Ctrl] + [D]、Macなら [Command] + [D] でマテリアルのファイルを複製しましょう。
複製したファイルはそれぞれ [PrefabCubeMagenta] 、[PrefabCubeYellow] に名前を変更します。
『PrefabCubeMagenta』を選択して色だけ変更しましょう。『Main Maps』の項目の中にある『Albedo』で色の部分をクリックし、カラーウィンドウで『Hexadecimal』の項目を [FF00FF] に設定します。あるいは『G』の項目を [0] にする方法でもOKです。同様に『Emission』の『Color』では『R』の項目に [64] 、『G』の項目に [24] 、『B』の項目に [64] を入力しましょう。
『PrefabCubeYellow』でも同様に色を変更します。『Albedo』の色として『Hexadecimal』の項目を [FFFF00] に設定します。あるいは『B』の項目を [0] に。同様に『Emission』の『Color』では『R』の項目に [64] 、『G』の項目に [64] 、『B』の項目に [24] を入力しましょう。
これらの設定が終わるとプロジェクトウィンドウでは以下のようになっています。
スクリプトの作成
さて、いよいよお待ちかねのスクリプト作成です。スクリプトも整理用のフォルダを作っておきます。
プロジェクトウィンドウで右クリックまたは二本指タップしてメニューを開き、[Create] -> [C# Script] を選択します。
作成したスクリプトの名前を [PrefabInstantiateSample] に変更しました。
ダブルクリックしてファイルを開き、編集していきましょう。
上から順番に解説していきます。
フィールドの宣言
publicなフィールドとして、以下の4種類を定義しています。
- Prefabとして使用するファイルへの参照
- 作成したオブジェクトを整理するための親オブジェクトへの参照
- 作成したオブジェクトにセットするマテリアル
- オブジェクトを生成する高さ
インスペクターウィンドウからセットできるようにpublicにしています。
Update()メソッド
Update()メソッドではちょっと変わった書き方をしています。
毎フレームオブジェクトが生成されるとちょっと多くなってしまいそうだったので、10フレームごとにオブジェクトを生成するようにしています。
ゲーム開始からのフレーム数を取得できる『Time.frameCount』のフィールドから値を取得し、それを10で割ったあまりが0ならオブジェクトを生成するメソッドであるCreateObject()を呼び出しています。
『%』を使うことで割ったあまりを取得することができるので便利です。(数学的には剰余と呼ばれています)
オブジェクトの生成
オブジェクトの生成ではInstantiateメソッドを使っています。
作成したオブジェクトの参照は「obj」の変数にセットしていて、後続の処理で使っています。
親オブジェクトをセットする場合はtransform.SetParent()を使います。引数で親オブジェクトの『Transform』を指定することでその子オブジェクトにすることができます。
続いて位置をセットしています。ここで指定する高さはフィールドとして宣言している「height」です。
乱数の取得ではRandomクラスのRangeメソッドを使っています。int型の乱数を取得する場合、第一引数は取得開始する数値、第二引数では取得終了する数値で、この値は含みません。
今回使いたいマテリアルは3種類なので0, 1, 2の数値を取得したいんです。第二引数の値が含まれないことから、3を指定しています。
取得した乱数に応じて対応するマテリアルを変えように設定していて、最後にそのマテリアルを『MeshRenderer』コンポーネントの『Material』の項目にセットしています。
親オブジェクトの作成
スクリプトを保存したらUnityのエディタに戻りましょ。ヒエラルキーウィンドウで何も選択していない状態でメニューを開き、[Create Empty] を選択します。
作成したオブジェクトの名前は [CubeParent] にしておきましょう。
作成した『CubeParent』のオブジェクトにスクリプトをアタッチしましょう。
スクリプトの各フィールドには対応するオブジェクトやマテリアルをセットします。『ParentTran』の項目はTransformコンポーネントへの参照をセットする項目になっていて、ヒエラルキーウィンドウから『CubeParent』をドラッグ&ドロップするか、『CubeParent』オブジェクトを開いている状態でインスペクターウィンドウから『Transform』コンポーネントをドラッグ&ドロップします。
その他の項目はプロジェクトウィンドウからドラッグ&ドロップしてセットしてください。
『Height』は [10] に設定してみました。この値はゲームの実行中にも変えられるのでいろいろ変えて遊んでみてください。
ゲームの実行
ゲームを実行すると以下のようにオブジェクトがどんどん生成されます。この画像だと『Height』の値を [20] にしています。
同じ位置に生成しているのに飛び散らばっている理由ですが、『Cube』オブジェクトにアタッチされている『BoxCollider』コンポーネントが関係しています。
コライダーによってオブジェクトが重ならないように位置を計算し直してくれるのですが、計算し直した後の位置でも重なっている場合はさらに重ならない位置になるように計算します。ここで重ならないように力を加えているため、本来は真下に落ちるはずの『Cube』オブジェクトがいろんな方向に飛んでいます。
ちなみにマテリアルのEmissionを設定しているので、暗闇の中でもほんのり光っています。なんだか昔のPCのスクリーンセーバーみたいな感じになりました。
まとめ
Prefabをインスタンス化するサンプルを紹介しました。今回のサンプルが何かの役に立つかというと……直接何かの役に立つわけではありませんが、インスタンス化した後に親オブジェクトを設定する、位置を設定する、といったあたりは実践でもよく使われる部分かと思います。
こういった遊びを入れながらゲーム作りを進めていくと気楽に技術も身についていくのでよかったらいろいろと試してみてくださいな。
おまけ
このページのコードではオブジェクトを作成してそのままですが、実際に使うときには必要なくなったオブジェクトを削除することも多いです。削除についても確認したい場合は以下の記事をご参照ください。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【Unity】Destroyで不要なゲームオブジェクトを削除【スクリプト】 2020.09.04
-
次の記事
【ゲーム作り】登場人物の行動理念を考えるヒント【ストーリー】 2020.09.06
コメントを書く