前回の続き。
お約束 | |
---|---|
この記事作成にあたって使用した主なUnreal Engine バージョン | UE 5.1.1 |
本日のゴール
LyraでワールドにPlayerスタートを配置すると、自動的にBotが生成するように設定する
Botのアクター選択
Bot生成に関して、下記のように担当が分かれています。
① Bot 生成時、どのPlayerStartでSpawnするか? → 前述の通り、「LyraPlayerSpawningManagerComponent」の「ChoosePlayerStart」関数
② Bot 生成時、どのAI Controllerを使うか? →どういうことをするのか?
③の「B_PickRandomCharacter」でGet Ownerを使うと、Controllerが取り出せるので、そこからなら情報が取り出せそうな感じがします。
そのコントローラー内に、情報を格納しておくようにします。
そのコントローラーは、②の「LyraBotCreationComponent」で生成するので、そのときに情報を渡してやればいいわけです。
というわけで、「LyraBotCreationComponent」でAIコントローラー「LyraPlayerBotController」をスポーンするときに、同時にBotのクラスを渡してあげるようにします。
目指す図は上記になっています。なんでこんなに面倒くさい手順にするかというと、各Botで保存する自分のBotクラスを変えたいからですね。
「LyraPlayerBotController.h」のPublic:直下
- /** Bot Class Num to specify PlayerStart */
- UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Bot", meta = (ExposeOnSpawn = true))
- int BotClassNum;
まずはBotClassNumというint変数を用意してあげます。
これをSpawn時に渡してあげたいので、
「LyraBotCreationComponent.cpp」の「SpawnOneBot()」内に追加
- FActorSpawnParameters SpawnInfo;
- SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
- SpawnInfo.OverrideLevel = GetComponentLevel();
- SpawnInfo.ObjectFlags |= RF_Transient;
- AAIController* NewController = GetWorld()->SpawnActor<AAIController>(BotControllerClass, FVector::ZeroVector, FRotator::ZeroRotator, SpawnInfo);
-
- //下記追加
- if (ALyraPlayerBotController* NewBotCon = Cast<ALyraPlayerBotController>(NewController)) {
- NewBotCon->BotClassNum = 1;
- }
ALyraPlayerBotControllerにCastするために、ALyraPlayerBotControllerを読み込んでおきます。
「LyraBotCreationComponent.cpp」の一番初め
- #include "Player/LyraPlayerBotController.h" // 追加
上記の例では、LyraGameInstanceからGetするのは一旦飛ばして、とりあえず1で指定しています。
また、オプションですが「LyraPlayerSpawningManagerComponent.cpp」でLyraPlayerBotContorollerからBotClassを読んでおきます。
前回のコードの中の、Botに関する部分を変更します。
- else if (!(Player->IsPlayerController())) {
- if (ALyraPlayerBotController* BotControllerDayo = Cast<ALyraPlayerBotController>(Player)) {
- int botclassnumref = BotControllerDayo->BotClassNum;
- for (auto StartIt = CachedPlayerStarts.CreateIterator(); StartIt; ++StartIt)
- {
- if (ALyraPlayerStart* Start = (*StartIt).Get())
- {
- if (Start->GetLocationOccupancy(Player) == ELyraPlayerStartLocationOccupancy::Empty) {
- if (Start->BotPlayerStartTag == FName(TEXT("Bot"))) {
- if (Start->BotClass == botclassnumref) {
- PlayerStart = Start;
- break;
- }
- }
- }
- }
- }
- }
- }
何がなんだかって感じですが、やってることは単純で、BotControllerが持っているBotClassと、PlayerStartが持っているBotClassが一致するときにだけ、そのPlayerStartを使ってSpawnするということです。
要するに、AというBotはA というPlayerStartしか使えなくなるというだけです。
あとは簡単だよね
あとは「B_PickRandomCharacter」でLyraPlayerBotControllerにCastして、情報を取り出すだけですね。
こんな感じで、LyraPlayerBotControllerにCastして、そこからBotClassを取り出し、BotClassによってアクターを選択できるようにします。めでたしめでたし・・・と思ったら・・・
常に0になるじゃん
実はLyraPlayerBotControllerにBot Classが設定される前に、上記ブループリントが働いてしまうのでこのような結果になります。
こういった場合はいくつか対処手段がありますが、一番正攻法のEvent Dispatcherを使ってみましょう。
- DECLARE_DYNAMIC_MULTICAST_DELEGATE(FChangeBotNum);
そしたら、次にPublic:直下に下記を追加します。
- /** Register Delegate */
- UPROPERTY(BlueprintAssignable)
- FChangeBotNum OnChangenumevent;
次に、「LyraBotCreationComponent.cpp」の「SpawnOneBot()」内に追加した内容を修正
- //下記追加
- if (ALyraPlayerBotController* NewBotCon = Cast<ALyraPlayerBotController>(NewController)) {
- NewBotCon->BotClassNum = 1;
- NewBotCon->OnChangenumevent.Broadcast(); //さらに追加
- }
あとは「B_PickRandomCharacter」でEvent Dispatcherを使うだけです。
0 件のコメント:
コメントを投稿