【UE5】敵キャラやアイテムをランダムに沢山スポーンしたい！

## 完成イメージ
完成イメージはアイテムだと下のような感じ，

<img width="600" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/7b36230e-1ce7-7272-9aab-138420b12244.gif">

https://imgur.com/a/NOepZa4

キャラクターだと下のような感じになります！
（敵キャラを召喚するシーンとかにどうでしょうか？）

<img width="600" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/12e4d29f-c6c1-f91c-52b3-7b248fb04162.gif">

https://imgur.com/a/xL2SwKd

### 環境
Unreal Engine 5.1.1（日本語）

## BulePrint
BPは下のリンクからコピーできます．
時間がない人はコピペしてパラメータや変数をセットすれば動くようになってます！

https://blueprintue.com/blueprint/1yzjpbp3/

## はじめに
アイテムをランダムに沢山配置するだけのページは結構見つかったんですが
スポーンしたキャラクターのアニメーションが止まったりして
困ったので備忘録も兼ねて記事を書こうと思います！

## 目的
アクタ（アイテムなどのオブジェクト）やキャラクター（敵キャラなどの移動可能なMob）を
できるだけ**シンプルかつ簡単に**指定した範囲にランダムに指定した数配置すること

## 方法
### スポーンさせるキャラクタの用意
まずはコンテンツブラウザで右クリックしてブループリントクラスを選択します，
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/3c69a1ff-e21b-3ef5-cc9b-4f35fa75af20.png)
`Character`を選択します．

:::note info
動かないアイテムなどのオブジェクトの場合でも`Character`を選択することをオススメします！
コントローラ関連を簡単に済ませるため，この後で`Spawn AIForm Class`を使うためです．
自分で解決できる方はぜひActorなどで試してみてください！
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/30f32b75-c371-8680-5df2-b824f1c363af.png)
今回は，キャラクタ（アニメーションつき）はMetaHumanを使って下のような感じに，
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/fcb0ad4f-6e61-db1a-8679-08e807d47af2.png)
アイテムはCubeに光るマテリアルをセットして下のような感じにしてみました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/399a1b5c-affb-8cd3-64a2-026091b52e87.png)

キャラクタやアイテムは自分で好きなものを用意してみてください！

ここまで出来たら次はスポーンエリアを決めるアクタを作っていきます．

### スポーンエリアを決めるアクタの作成
まずはコンテンツブラウザで右クリックしてブループリントクラスを選択します，
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/3c69a1ff-e21b-3ef5-cc9b-4f35fa75af20.png)
アクタを作成します．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/5c3d7c68-7d21-a5f3-b3b4-df4e6fbc411c.png)
今回は名前を`SpawnArea`としました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/494b883f-b5b7-b920-950b-675462ca20d1.png)
作成したアクタをダブルクリックして編集画面を開き，コンポーネントの追加から`Box Collision`を追加します．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/7deb26e1-f691-8829-7bab-62b4bb890595.png)
追加できたら一度コンパイルしましょう．
イベントグラフタブに移動してカスタムイベントを追加します．
カスタムイベントの名前は`Spawn`としました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/d87f82ae-dab8-15fe-0801-7ebf0fde48bc.png)
### スポーンするBPの作成
ここからがこの記事のメインになります！
オブジェクトやキャラクタをスポーンさせるための`Spawn AIForm Class`ノードを作成します．
`Pawn Class`には先ほど用意した`Character`オブジェクトをセットします．
`Behacior Tree`には今回は何もセットしません．

:::note info
もしキャラクタの行動をセットしたい場合には`Behacior Tree`に用意したものをセットします．
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/5270feac-db2e-8bda-5893-b2fa1dce237a.png)
どこにキャラクタをスポーンさせるか決める`Location`にはアクタのBoxの内側の座標からランダムに選択することにします．
BoxCollisionコンポーネントから`GetComponentBounds`ノードで当たり判定を取得して`RandompointBoundingBox`ノードでランダムに一点の座標を選びます．

キャラクタのスポーンしたときの向きを決める`Rotaion`には`RandomRotator`ノードでランダムな回転をセットします．

:::note info
この辺りは用途に合わせて変更してみてください！
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/726d9978-5cf8-8c4b-eba6-326f0ab259f9.png)
このままだと一回のイベントにつき1つのキャラクタしかスポーンしないのでループをつなげておきます．
LastIndexにお好みの回数をセットしてください．今回は5回にしました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/2bb0741f-876d-d4da-930b-8e9b3e53a1e6.png)
これでおおまかにキャラクタをスポーン出来るようになったのでイベントを呼び出す機能を作成してみましょう．
`EventBeginPlay`ノードを引き出して，`SetTimerByEvent`ノードを繋げます．
今回は3秒に1回スポーンすることにしたいので`Time`に`3.0`をセットしておきます．
`Event`を先ほど作成した`SpawnArea`とつなげておきます．

:::note warn
あまり短い頻度でスポーンするようにするとエディタがかなり重くなるので気を付けてください！
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/aa73d3c1-5ab4-78bc-9e72-d042255dea37.png)

上記のBPでキャラクタをスポーンさせていると，たまに指定した数より少ない数しかスポーンしません．
これは既にスポーンしているキャラクタとスポーン位置が被ったりしているときにスポーンしないようになっているためです．
スポーンに失敗したらリトライしてほしいので失敗したらループする機能を付けます．

まず，失敗した回数をカウントする変数を作成します．
今回は`MissCount`という名前を付けました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/2ad155d2-6e80-ea82-4d23-295a54fcda4b.png)
`Spawn AIForm Class`ノードのあとに`Is Valid`ノードをつなげてスポーンしたオブジェクトが存在するか（＝スポーンに成功したか）を確認します．
スポーンに失敗していたら`MissCount`をインクリメント（+1）します．
50回以上失敗しているとしたらスポーンするエリアが何かにふさがれているなど何かしら問題が起きていると判定してエラーメッセージを出力して次のループにいくようにします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/a15b69d3-957e-0424-886e-432b41756622.png)

これでキャラクタをスポーンするアクタのBPが出来ました！

### アクタの配置
キャラクタをスポーンさせたい位置に先ほど作成した`SpawnArea`アクタを配置します．
ボックスのサイズを拡大してスポーンしてほしい範囲まで広げます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418961/fd08f2bc-ca71-5e75-7325-f736ea8f41a5.png)

これで完成です！実行してみましょう！

## おわりに
最後まで読んでいただきありがとうございます！

初投稿なので色々足りない点があるかと思いますが，何か気づいことがあったらコメントや編集リクエストなどでコッソリ教えてください....

それから，Twitterをやってるのでもしよければフォローしていってください！
↓ 今回の記事の内容を実行したときのツイート

https://twitter.com/OmOti_UE/status/1642028240788398080?s=20