PavilionDV7の雑多なやつ

Qiitaから移行しました。UE4に関する記事から興味のあることまで色々書きます。

【UE5】敵キャラクターのスポナー(Spawner)を作る

はじめに

第19回ぷちコンに提出したゲームで実装した敵キャラクターのスポナーの実装を紹介する。

youtu.be

実装開始

基礎部分

実装するブループリントは「Actorクラス」を継承したブループリントとする。

コンポーネントはルートに「Box Collision Component」を設定したのみ。プロパティのBox ExtentのY軸の値を1000ほどにセットしておく。


Event Graphに次のように実装する。

Spawnイベントでは実際にアクターをスポーンした後、SpawnイベントをSet Timer by Eventノードで1秒後に再実行されるようにセットしている。これでSpawnイベントは1秒毎に呼び出されるので、アクターも1秒間隔でスポーンする。

決まった秒数を繰り返すだけならSet Timer by EventノードのLoopingフラグにチェックを入れるのが正攻法。ただし今回はスポーン間隔をプレイ中に変更したいのでこのような実装にした。

Spawn Transform Locationにて使用しているRandom Point in Bounding Boxは、文字通りCenterとHalf Sizeによって定義される直方体の範囲でランダムな位置を返す。今回はBox CollisionコンポーネントのBoundsを指定しているので、Box Collisionコンポーネントのサイズ内のランダムな位置を返すようになっている。

Spawn Actor from Classに指定しているブループリントクラスは一定間隔でスポーンすることを確認できるようなアクターであれば何でもいい。画像で指定したBP_Moverは次のように実装している。

スポーンレートをゲーム中に変化させる

スポナーブループリントのTickイベントに次のような処理を追加する。

毎フレーム、デルタ秒を加算することで経過時間(Elapsed Time)を求める事ができる。この経過時間をMap Range Clampedノードで0.0 ~ 1.0の数値に変換する。今回の実装では経過時間が10秒になったときMap Range Clampedノードは1.0を返すことになっている。

続いてSpawnイベントのSet Timer by Eventノードを次のように修正する。(Set Timer by Eventノードにあるコメントは消し忘れなので気にしないで)

Spawn Rate RatioとLerpノードの組み合わせでSet Timer by Eventに渡されるTimeの値は1.0 ~ 0.1に減少していく。Timeの値が減れば減るほどスポーン間隔が狭まるため多くのアクターがスポーンされることになる。

おまけ

スポーンされるアクターの確率を設定する

提出したゲームには4種類の敵キャラクターがいる。それぞれ移動速度や体力が異なるため、同じように出現してしまうと極端なゲームバランスになりゲームプレイが難しくなる可能性があったので、体力が多い敵は出現確率を低く、体力が少ない敵は出現確率を多くといった出現確率を設定できるように実装した。

このような偏った確率でランダムにアイテムを取り出すような仕組みを「重み付きランダム」「重み付きランダムサンプリング」「Weighted Random」と呼ぶ。

実装は次のようになる。

使い方として「文字列を格納した配列から重み付きランダムで文字を取り出す」例を示す。

各配列要素への重み(出現確率)は次の画像の赤線、緑線、青線に対応している。

試しに300のループを回して「Normal」「Fast」「Tank」の出現回数を調べてみた。

[BP_Spawner_C_1] Normal : 149 Fast : 97 Tank : 54

Normalが149個、Fastが97個、Tankが54個なので、それぞれを300で割ると

Normal : 149 / 300 = 0.49666...
Fast   :  97 / 300 = 0.32333...
Tank   :  54 / 300 = 0.18

となり、おおよそ出現確率テーブルで設定した値通りの結果が出ている。

【UE4/UE5】ブループリントでアイテムドロップ率とかに使う重み付き抽選を行う

【Unity】重み付きの確率抽選を行う方法 | ねこじゃらシティ

重み付き乱択を行う - Carpe Diem