UE5初心者がアイテムの種類や出現場所をランダムに決定する方法(&順番に決定する方法)について調べてみた!
▼続きは「本文を読む」からどうぞ~!
- ①Target Pointがある場所にアイテムをランダム出現させる方法
- ②BP配置によってランダムな種類のアイテムを出現させる方法
- ◆出現アイテムと出現地点の両方をランダムに抽選する
- ◆出現アイテムはランダムだけど出現地点だけ順番にずらす
- ◆敵AIをNavMeshの範囲内にランダム出現させる
- ◆「地点」ではなく「範囲」を指定してランダム出現させる方法
- ◆まとめ
①Target Pointがある場所にアイテムをランダム出現させる方法
▲参考動画(英語)。UE4の内容だけどUE5でも通用した。
上の動画では「あらかじめ設定した数か所の地点(Target Point)から出現地点をランダムで抽選し、そこにアイテムを出現させる方法」が解説されている。
※ちなみに後で紹介する「Target Pointを使わずにBPで出現させる方法」の方が初心者向けだと思う。
- 画面左上[SelectionMode∨]の隣にある[+]ボタン>[All Classes]>[Target Point]をレベル上へ配置する。
UE5だとUIが違うので注意。 - レベルBPを別タブとして開いておく。
- メイン画面の[Outliner]欄に戻り、追加した[Target Point]をShiftで複数選択してレベルBPの方へドラッグ。
- [Make Array]でTarget Pointから配列を作成。
- 配列データを[Get(a Copy)]で取得。
- [Random Integer in Range]でindex数の参照時に使う乱数を出力し、どの地点に出現させるかランダムで選択する。
- [Get Actor Transform]でランダムに選択したTargetPointの座標を獲得する。
- その座標に対し、[SpawnActor from Class]で指定したClassのBPを生成する。
▲レベルBPに書くノード(FullScreenからコピペ画面へ移行&ESCで離脱)。
初心者でも3分あれば実装できるお手軽なBPで本当に助かった…!
- ただ、この仕様だとゲームを開く度にスポーン位置が再抽選される形なので、ゲーム内で使うなら「一定時間ごとに一連のスポーン作業を繰り返し実行する」仕組みにした方が実用的かもしれない。
▲指定したアイテムがいくつかの地点にランダムで出現し続ける(同時に2つ存在することは無い)パターン。
これで「一定時間経ったら消滅してまた別の地点にリポップする」機能を実装できた。
- 最初、[Set Timer by Event]の実施間隔=消滅までのDelay秒数にしてみたら、ときどき異常な遅延が発生しアイテムの出現CDも不安定になった。
(※アイテム出現のCDを5秒に設定したはずなのに10秒まで伸びたりしていた) - ChatGPTに質問したところ、[Set Timer by Event]は前回のイベントが終わってから再起動するノードだから遅延で再起動がズレているかもしれないと言われた。
実施間隔(秒)=カスタムイベント内のDelay(秒)にした場合、Delay側が0.1秒遅延するだけでSetTimerは1周分の実行をサボってしまうらしい…w - 少しくらい処理が遅延しても良いようにDelay側を0.1秒~0.5秒ほど低めに設定したら無事解決できた!
②BP配置によってランダムな種類のアイテムを出現させる方法
ずっと同じ種類のアイテムだけスポーンさせるのはつまらないから、出現する種類をランダムにする方法も調べてみた。
▲参考動画(英語)。
※さきほどのTarget Pointを作る動画とは違って、「ランダムなアイテムが1個出現するBPを作り、そのBPをレベル上に複数配置していく」という内容。
▲コピペ用ノード(ランダムアイテムBPに書く)
- ランダムなアイテムの発生元となるスポーンBP(親Actor)を新規作成。
- 出現アイテムになるBPも数個作っておく。
- スポーンBPのコンポーネント欄に[ChildActor]を追加し、ノードの作成へ移る。
- [Select]ノードの紫ピンを右クリックして[Promote to Variables]で変数化する。
(この変数は出現させたいアイテムの種類と同じ数だけ作る) - [Variables]欄で変数の名前と参照元を変更する。
※型名の欄からBP名で検索>右にマウスをずらし紫色[Class Reference]を選ぶ。 - 一旦コンパイルして変数の[Default Value]欄からアイテムBPと紐づける。
▲動画の内容をふまえて、一定時間ごとにアイテムが初期位置へ再出現&再抽選されるよう改善してみた。
実際にゲームを作る時は、このスポーンシステムを使ってみる予定…!
- 上記BPをレベルへ複数配置すれば、それがアイテムの出現地点になる。
- ①②のやり方を両方試してみたけど、②の改善バージョン(すぐ上のやつ)が1番楽だし実用的だと思った。
◆出現アイテムと出現地点の両方をランダムに抽選する
▲一応、「Target Point」を利用する①のパターンへ戻って、出現地点と種類がランダムに決定されるよう修正してみた(記述先はレベルBP)。
◆出現アイテムはランダムだけど出現地点だけ順番にずらす
▲アイテムの出現場所だけがA>B>C>Dと順に変わっていくパターンも試した。
(「Target Point」を使うパターン・記述先はレベルBP。
アイテムの種類はランダム抽選のまま、出現場所だけ規則的になる)
規則正しく出現場所を決定する方法は、使いどころがあまり思い浮かばない…w
◆敵AIをNavMeshの範囲内にランダム出現させる
▲下準備として、この動画で説明されているシンプルな鬼ごっこAI(敵)を作る。
▲参考動画(英語)。
- NavMesh(AIが動ける範囲を指定するパーツ)は、メイン画面左上の[+ボタン]>[Volumes]>[New Mesh Bounds Volume]からレベル上へ追加できる。
- 配置後、敵AIの稼働範囲がすっぽり覆われるくらいサイズを大きくする。
- [P]キーからAIが移動可能な緑色の範囲を表示してみて、ちゃんと全エリアをカバーできているか確認する。
▲追いかける敵のBP(親Character)。
▲敵BPを出現させるためのスポーン用BP(親Actor)。
[Get Random Reachable Point In Radius]は、指定されたターゲットを原点とする円の中のランダムな座標を取得してくれるノードらしい。
※座標と言っても円の中ならどこでも良いわけじゃなくて、NavMesh(AIが行動できる緑色の範囲)の中だけ取得するようだ。
※[Radius]ピンから円の半径を指定する。
- 前回、追尾ドローンを親アクター/親ポーンのBPとして作ったけど、絶対に親がキャラクターのBPとして作ってNavMesh+Move toを活用した方が良かった。
- 思った以上に手軽そうなので、敵AIについてもっとちゃんと調べてみたい!
▲ランダムな方向を向いた状態で敵が4秒ごとに再出現するよう変更したバージョン。
◆「地点」ではなく「範囲」を指定してランダム出現させる方法
▲あらかじめ複数の出現地点を指定するやり方以外に、BoxCollisionなどで出現範囲(空間)を指定してランダム出現させるやり方もあった。
▲参考記事を読んで作ってみたスポーンBP(親Actor)。
※[Spawn AI from Class]から[Spawn Actor from Class]へ変えれば、敵AIではなくアイテムをスポーンさせられる。
- [Get Component Bounds]で対象に指定したコンポーネント(※参考記事内だとBoxCollision)が置かれている空間のデータを取得する。
- そこから[Random Pointing Bounding Box]で対象コンポーネント(BoxCollision内)のランダムな位置情報を出力する。
- 出力した位置情報を[Spawn AI from Class]のLocationとして入力する。
- 敵AIの向きを0度~360度の範囲内で変えたい場合、[Random Rotator]のZ値だけ取り出してSpawnノードの角度入力ピン(Z)へ繋げる。
(ピンの分割はノード上で右クリ>[Split Struct Pin]からできる)
ひとまず敵AIの出現用として上記BPを使ってみたものの、前述した[Get Random Reachable Point In Radius]よりバグりやすい気がした。
どちらかといえばアイテムスポーンのために使った方が良いかもしれない…?
◆まとめ
今回はスポーン専用のBP(親Actor)を作って点・円・箱の中にランダム出現させる方法とTarget Point+レベルBPでランダム出現させる方法を2通り学んだ。
- 【アイテム(種類ランダム)をたくさんの場所で同時にリスポーンさせる】
初心者だと、スポーン用BPを作ってレベル上にいっぱい配置するやり方が1番分かりやすそう。 - 【アイテム(種類ランダム)を数か所で順番に出現させ続ける】
Target Point+レベルBPのやり方が向いてるかも。 - 【敵AIをランダムな位置に出現させる場合】
[Get Random Reachable Point In Radius]を使うやり方が1番楽だと感じた。
※NavMesh(AIが移動可能な範囲≒地形)も考慮したうえで、ちょうど良い場所に敵を生成してくれるので便利だった。