UnityでRPGゲームのワールドマップに敵を自動生成する機能

記事内に広告が含まれています。

今回は、RPGゲーム等のワールドマップに自動で敵を生成する機能を作成したいと思います。

今回の機能は、ワールドマップシーン→戦闘シーン→ワールドマップシーンというRPGの流れを作ってみようと思ったんですが、全てを1つの記事にすると長くなってしまうので、

まずは第1弾として、ワールドマップシーンが読み込まれた時に敵を自動で配置する機能だけをやってみることにしました。

敵を配置するには、ワールドマップ上に敵が出現する場所をあらかじめ作っておき、そこから敵を生成する方法もあります。

こちらの方が特定の場所から敵を出現させる事が出来るので、不具合が発生しませんし、管理がしやすいかもしれません。

今回作成する機能は、ワールドマップシーンが読み込まれた時に毎回新しく敵をマップに配置する機能です。

その為、戦闘シーンへと遷移した後にワールドマップシーンが読み込まれたら前の状態は破棄されています。

前の状態を維持したい場合は、ScriptableObjectを使って敵の配置データを記憶してワールドマップシーン読み込み時にその場所に敵を配置したりする必要があります。

今回は毎回新規に配置するということで・・・・。

今回の機能は以前作成したUnityEditor上で、ゲームオブジェクトを自動配置する機能をゲーム中に使うよう改造します。

UnityのTerrainにゲームオブジェクトを自動配置するツールを作成する
UnityのTerrainの地面に合わせて建物や木等のゲームオブジェクトを回転やサイズを変更して指定した数だけ配置するツールの作成。
スポンサーリンク

ワールドマップの作成

まずはワールドマップを作成していきます。

ワールドマップはTerrainを使って作成します。

Terrainの使い方は

UnityのツールTerrainを使ってフィールドを作成する
UnityのツールTerrainを使ってゲームの地形フィールドを作成していきます。

を参照してください。

作成したワールドマップのTerrainの子要素にサイズを調整したCubeを配置します。

簡易ワールドマップのヒエラルキー

↑のようなヒエラルキーになります。

ワールドマップは、

簡易ワールドマップ

↑のようになります。

Cubeは建物に見立てて設置しました。

Terrain自身のレイヤーにはField、子要素のCubeにはBlockというレイヤーを作成し、設定しておきます。

Terrainのサイズに合わせて位置を調整

今回のTerrainは設定でTerrain Widthを50、Terrain Lengthを50に設定しました。

その為、Terrainの位置をXを-25、Zを-25にして、Terrainの真ん中がX、Y、Zで0の位置にくるようにします。

配置する敵をプレハブ化する

あらかじめ敵として配置するゲームオブジェクトをAssetsフォルダにドラッグ&ドロップしてプレハブ化しておきます。

自動生成する敵をプレハブ化しておく

↑のように敵をプレハブ化しました。

本来であればワールドマップで敵が動く為にCharacterControllerを取り付けたり、動くスクリプトを取り付けた物をプレハブ化しますが、

今回は設置するだけなので特別な機能は取り付けません。

敵のプレハブのレイヤーにはMonsterを作成し、設定しておきます。

敵を自動配置するスクリプトの作成

それでは敵を自動配置するスクリプトを作成します。

敵を自動生成するスクリプト全文

スクリプトの設定部分

terrainには先ほど作成したTerrainを設定します。

maxNumは敵を生成を試みる最大数を設定します。試みる数なのでこの数分だけ必ず敵が生成されるわけではありません。

monstersには配置する敵のプレハブを全て設定しておきます。

radiusは他の敵と接触を計算する時の半径を指定します。

地面にはField、家等の建物にはBlock、敵にはMonsterというレイヤーを設定しましたが、敵自身には主人公キャラクターとの接触を判定する為のコライダを設定する必要があるので、敵を生成した直後に主人公と接触判定をされてしまうと不具合が発生してしまうので、radiusにはその範囲よりも大きい値を指定します。

例えば、敵が主人公と接触したと判定するコライダをSphereで作成しその半径を1としていた場合は、このスクリプトのradiusには1より上の数値を指定します。

敵を生成するInstantiateEnemyメソッド

InstantiateEnemyメソッド内では、生成した敵の親のゲームオブジェクトを生成し、敵のゲームオブジェクトを全てこのゲームオブジェクトの子要素にします。

for文を使ってmaxNum回の敵の生成を試みます。

Terrainの位置とサイズからランダム値を計算し、Y座標はTerrainから上に100に設定し、その位置から下側に球のレイを飛ばします。

Fieldレイヤーと接触していたら、次の条件を判定します。

次の条件は同じ位置から球のレイを飛ばし、Player、Monster、Blockレイヤーが設定されているゲームオブジェクトにぶつかっていないかどうかを判定します。

ぶつかっていなければ地面の接触ポイントに敵をインスタンス化し配置しています。

2つめのif文では接触していない時を判定しているので,out hitという引数はいらないような気がしますが、ない場合のコンストラクタが定義されていなかったので、

記述してます。

判定条件としては接触していない時に実行し、hitの値は変わらないと思うので、地面の接触点が取得出来ると思います。

インスタンス化したゲームオブジェクトはUnityのスクリプトリファレンスにあるとおり、同時に親の設定も出来ます。

Object-Instantiate - Unity スクリプトリファレンス
original のオブジェクトをクローンします

ですが、わたくしのUnity5.3.4f1だと定義されていないっぽいので、個別に親のゲームオブジェクトを設定しています。

出来る方はInstantiateの引数に指定した方がいいです。

今回の敵のプレハブの角度は全てQuaternion.identityと親の要素の角度と同じに設定していますが、例えばY軸の角度だけ変更して、別の方向を向かせる事も可能です。

Quaternion.identityの部分をQuaternion.Euler(0f, Random.Range(0f, 360f), 0f)

とすればY軸の角度だけをランダムにし設定する事が出来ます。

これで自動生成スクリプトが完成しました。

敵を自動生成してみる

スクリプトが出来たので何らかのゲームオブジェクトに取り付けておいて、GenerateEnemyスクリプトのInstantiateEnemyメソッドを実行してみてください。

確認するだけならInstantiateEnemyメソッドの部分をStartに書き換えて、スクリプトを設定したゲームオブジェクトが出現した時に自動実行させた方が楽かもしれません。

次回以降にScriptableObjectを使ったシーン間の移動の機能を作成しますが、そこに今回の機能を使う場合は少しやり方を変える必要があります。

GenerateEnemyのインスペクタは

GenerateEnemyのインスペクタの設定

↑のように設定しました。

実行すると、

敵を自動生成して配置した画像

↑のように敵が地面に配置されました。

真ん中辺りに主人公役のEthanもいるんです。(^^)/

建物であるCubeはBlockレイヤーを指定し、敵はMonster、主人公はPlayerを設定しているので、敵を生成する時はそこには配置されていません。

レイで地面との接触位置を調べているので、

凸凹に合わせて敵が配置される

↑のようにTerrainのデコボコに合わせて敵も配置されます。

敵を設置したくないエリアには透明なゲームオブジェクトを配置し、レイヤーをBlockに設定すればそのエリアには敵が配置されないようにも出来るので、敵を単純に配置したい時は便利かもしれません。

これで第1弾終了です。

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