【Unity】スクリプトからブロック崩し用のPrefabを配置するサンプル
UnityではPrefabを用意しておくことで、スクリプトからインスタンス化することができます。ゲーム実行中にたくさんのオブジェクトを生成したい場合はこの機能をマスターしておくと開発が捗ります。
この点については以下の記事で解説を行っています。
このページでは、上で紹介したページでちょっと紹介した、ブロック崩しのブロックを配置するサンプルコードを解説付きで紹介します。
こうしたサンプルを通して機能を確認していくことも大切なので、あなたのコーディングの引き出しを充実させる材料になれば嬉しいです。
環境
macOS Catalina 10.15
Unity2019.4.4f1
参考文献
UnityのマニュアルでPrefab(プレハブ)について解説されているのでこちらもご覧ください。
こちらはUnityのスクリプトリファレンスです。Instantiateメソッドの使い方が記載されています。
PrefabをInstantiateする
スクリプトからPrefabをInstantiateする方法については、以下の記事に詳しく記載したのでこちらもぜひ。
ブロック崩し用のブロックPrefabを配置するサンプルサンプル
以下の画像のように、ゲーム開始時にたくさんのプロックが並んでいるようなサンプルを作成したいと思います。
このサンプルでは以下のことが学べます。
- PrefabをInstantiateする
- 生成したオブジェクトの親オブジェクトを設定する
- 乱数によって処理を分岐させる
- スクリプトからオブジェクトのマテリアルを変更する(ちょっと発展)
Cubeを作成
まずはPrefabとして作成する『Cube』オブジェクトを作成します。サンプルでは『Cube』にしていますが、3Dのオブジェクトであれば『Sphere』でも『Capsule』でもOKです。
もし以下の記事で既に作ってあるCubeがあればそれを使いまわしてもOKです。
この『Cube』オブジェクトに『Rigidbody』コンポーネントをアタッチします。設定値はこのままで構いません。あ、緑にしているのはUnityの画面でそう表示されるのではなく、私があとでPhotoshopで色をつけているだけです。念のため。
作成した『Cube』オブジェクトをプロジェクトウィンドウにドラッグ&ドロップします。こうすることでPrefabのアセットファイルが作成されます。Prefabのアセットファイルは任意のフォルダを用意しておくと整理しやすいと思います。
Prefabが作成されると以下のようにアセットファイルが表示されます。
Prefab作成後は、シーンにある『Cube』オブジェクトを削除しておきましょう。ヒエラルキーウィンドウで『Cube』オブジェクトを選択している状態で右クリックまたは二本指タップしてメニューを開き、[Delete] を選択します。
Planeの作成
『Cube』のPrefabを並べるオブジェクトとして『Plane』を作成します。ヒエラルキーウィンドウで何も選択していない状態で右クリックまたは二本指タップしてメニューを開き、[3D Object] -> [Plane] を選択します。
作成した『Plane』オブジェクトで『Transform』コンポーネントのPositionとScaleを設定します。
Positionでは『X』を [15] に、『Z』を [5] に設定します。
Scaleでは全ての項目を [5] に設定しましょう。
Main Cameraの設定
ブロックを配置した時に画面に映るようにカメラの位置も少し調整しましょう。
ここでは『Transform』コンポーネントのPositionで『X』を [15] に、『Y』を [20] に、『Z』を [-25] に設定しました。また、少し見下ろした形で映せるようにRotationの『X』の値を [45] に設定しています。
カメラの位置は大体の位置にしてあるので、見やすいように設定を変更してもらえると嬉しいです。
マテリアルの作成
続いてマテリアルを作成しましょう。マテリアルについても、以下の記事と同じ作成手順になるので、こちらの『マテリアルの作成』という項目を参考に作成してください。
もし「とりあえず並べたいだけだから、マテリアルを使わなくてもいいよ!」という場合は、このまま次の手順に進んでもOKです。
スクリプトの作成
さて、いよいよお待ちかねのスクリプト作成です。スクリプトも整理用のフォルダを作っておきます。もし既に作ってある場合はそれを使ってくださいな。
プロジェクトウィンドウで右クリックまたは二本指タップしてメニューを開き、[Create] -> [C# Script] を選択します。
作成したスクリプトの名前を [PrefabPlaceSample] に変更しました。
ダブルクリックしてファイルを開き、編集していきましょう。
上から順番に解説していきます。
フィールドの宣言
publicなフィールドとして、以下の3種類を定義しています。
- Prefabとして使用するファイルへの参照
- 作成したオブジェクトを整理するための親オブジェクトへの参照
- 作成したオブジェクトにセットするマテリアル
インスペクターウィンドウからセットできるようにpublicにしています。
Start()の処理
Start()では次に紹介する『CreateBlockObject()』のメソッドを呼び出しています。ゲーム開始時に1回だけ作成してくれればOKなのでStart()から呼んでいます。
ブロックを作成する処理
CreateBlockObject()のメソッドでプロックを作成して並べています。
メソッドの冒頭で宣言している『row』は行数(Z軸方向のブロック数)、『column』は列数(X軸方向のブロック数)を表しています。
その下の『xOffset』と『zOffset』はブロックを並べる間隔です。作成した『Cube』オブジェクトのスケールに合わせて、まずは固定値で指定しています。
Prefabをインスタンス化する処理はfor文の中のfor文に入れています。外側のfor文はZ軸方向、内側のfor文はX軸方向を表していて、各行でひとつずつオブジェクトを配置していくイメージです。
Prefabからゲームオブジェクトを作成するにはInstantiateメソッドを使用します。インスタンス化する対象のPrefabを指定し、位置、回転を設定しています。
ゲームオブジェクトの位置は、ループのカウンタとして使っているi, jを使って計算しています。間隔を定義した『xOffset』や『zOffset』を使って位置を計算できるので、これをオブジェクトの位置としてセットしています。
マテリアルの設定
上でマテリアルの作成を行っていない場合は、「// マテリアルをランダムで設定します。」以降の部分は記載しなくてOKです。
マテリアルの設定部分では、セットするマテリアルを乱数を使って取得しています。ここでは単純に0, 1, 2の数値をランダムで取得するようにしていて、取得した値に応じてセットするマテリアルを切り替えています。
「Random.Range(0, 3)で3を指定しているのに0, 1, 2が返ってくるの?」と思われたかもしれませんが、実はRandomクラスのRangeメソッドでは、引数をint型で指定した場合は右側の値が含まれないんです。ここは結構初見キラーですね(笑)
引数がfloat型の場合は右側の値を含むので、これまたややこしいところです。この辺りはスクリプトリファレンスもご覧あれ。
親オブジェクトの作成
スクリプトを保存したらUnityのエディタに戻りましょ。ヒエラルキーウィンドウで何も選択していない状態でメニューを開き、[Create Empty] を選択します。
作成したオブジェクトの名前は [CubeParent] にしておきましょう。このオブジェクトの子オブジェクトとしてPrefabからゲームオブジェクトを作成していきます。
作成した『CubeParent』のオブジェクトにスクリプトをアタッチしましょう。
スクリプトの各フィールドには対応するオブジェクトやマテリアルをセットします。『ParentTran』の項目はTransformコンポーネントへの参照をセットする項目になっていて、ヒエラルキーウィンドウから『CubeParent』をドラッグ&ドロップするか、『CubeParent』オブジェクトを開いている状態でインスペクターウィンドウから『Transform』コンポーネントをドラッグ&ドロップします。
その他の項目はプロジェクトウィンドウからドラッグ&ドロップしてセットしてください。
ゲームの実行
ゲームを実行すると最初のフレームでブロックが並べられます。
ブロック崩しで初期配置を準備するのにも使えますし、ボウリングゲームでピンを並べるのにも使えます。スクリプトからオブジェクトを並べる処理を一度作っておけば、シーンウィンドウで手動で作成するあの地獄を味わうことなく楽にゲームの環境を整備することができます。
発展
上のスクリプトではオブジェクトの間隔を固定で入れていましたが、ブロックのScaleに応じて動的に設定できるともっと使いやすくなります。
例えば、横方向の間隔、縦方向の間隔をインスペクターウィンドウから設定できるようにして、配置する際にはPrefabのScaleも参考にするようにしてみましょうか。
オブジェクトを並べる間隔、数をインスペクターウィンドウで設定できるようにしました。
インスタンス化した後の位置決めの部分では、PrefabのScaleを確認して、これを考慮して位置を決められるようにしています。こうすることで、Prefabの大きさが変わったとしても、等間隔で並べることができます。
実際に動かしてみると以下のようになります。
Planeの位置が適当なのは目を瞑ってもらうとして、横長のブロックを自動的に並べることができました。こんな感じでオブジェクトに合わせて位置を計算できる仕組みを作っておくと色々と便利です。
まとめ
このページではPrefabのInstantiateの機能を使って、ブロック崩しで使うブロックをスクリプトから並べるサンプルを紹介しました。
私は個人的にPrefabのScaleを取得して位置を計算する、というのをよくやるのでおすすめしたいところ。色々応用ができるので便利なんですよね。
もしよかったらUpdate()からオブジェクトを生成するサンプルについても試してみてください。
ゲーム開発の攻略チャートを作りました!
-
前の記事
異なるアドバイスと出会った時の対処法【前提条件を知るのがベスト】 2020.09.13
-
次の記事
ゲームで使うBGMの候補を作業用BGMにするメリット 2020.09.15
コメントを書く