#はじめに
過去に書いたAIPerceptionの紹介記事(【UE4】AI Perception の紹介と使い方、【UE4】AI Perception の紹介と使い方 その2)では
AI Perceptionコンポーネントでは「コントローラー側にコンポーネントを追加する」という形になります。
と説明しました。
記憶が朧気なのですが、最初の紹介記事を書いた時点でAIPerceptionはAIControllerでアタッチされた時にしか動作しなかったと思います。ですので、紹介記事ではコントローラー側にコンポーネントを追加するようにと書きました。
最近AIPerceptionをCharacter側にアタッチして問題なく動作する場面(その時はAISense_Sightでした)を見てしまったので「Character側に付けても問題ないのならば、AIControllerに付ける意味とは一体...?」と考え、自分なりに検証してみたのでその結果を書いていきます。
#検証処理
検証に使用したバージョンは4.18.3です。
Characterを継承したBlueprintにAIPerceptionを付けたもの。AIControllerを継承したBlueprintにAIPerceptionを付け、Characterを継承しただけのBlueprintにそのAIControllerをセットしたものの2種類用意しました。
AIPerceptionが付いている方にはそれぞれ以下のような処理を追加しました。
AISense_TeamとAISense_Touchについては検証していません。
#検証結果
##AISense_DamageとAISense_Predictionは動作しない
【UE4】AI Perception の紹介と使い方 その2で紹介したAISense_DamageとAISense_PredictionはCharacter側にAIPerceptionを付けた場合、動作しませんでした。
AISense_Damage.cppで定義されている関数Updateは以下のように書かれています。
float UAISense_Damage::Update()
{
//~~ 省略 ~~
UAIPerceptionComponent* PerceptionComponent = PerceptionListener->GetPerceptionComponent();
if (PerceptionComponent != nullptr && PerceptionComponent->GetListenerId().IsValid())
{
// this has to succeed, will assert a failure
FPerceptionListener& Listener = ListenersMap[PerceptionComponent->GetListenerId()];
if (Listener.HasSense(GetSenseID()))
{
Listener.RegisterStimulus(Event.Instigator, FAIStimulus(*this, Event.Amount, Event.Location, Event.HitLocation));
}
}
}
}
RegisteredEvents.Reset();
//~~ 省略 ~~
}
PerceptionListener->GetPerceptionComponent()を呼び出しAIPerceptionComponentを取得しています。(この関数はAIControllerで定義されています)
Character側にAIPerceptionを付けた場合、関数GetPerceptionComponentはNULLが返り、刺激が登録されず、Blueprint側で書いたOnPerceptionUpdateが呼び出されません。
AISense_Predictionも関数Updateの形はほぼ同じなので同様の理由で受けた刺激が登録されず、OnPerceptionUpdateで定義したDamageとPredictionの刺激を受けた際の処理を通ることはありません。
##じゃあAISense_SightとAISense_Hearingは?
この2つの検証は上記で示した検証コードのブランチ部分をそれぞれAISense_SightとAISense_Hearingに変更し、PrintStringの内容を変えただけです。
AISense_SightやAISense_HearingはAIPerceptionを付けた時に必ずと言って良い程追加される刺激ですが、この2つの刺激についてはCharacter側に付けようがAIController側に付けようが問題なく動作します。
エンジンコードを見てみると2つのクラスの関数Updateでは関数GetPerceptionComponentを呼び出し条件分岐させるような部分が無いため、Characterに付けてもAIControllerに付けても影響は受けないものと思われます。
#結論
簡単な検証ではありますが得られた結果として
Character側にAIPerceptionを付けた場合AISense_SightとAISense_Hearingは動作するがAISense_DamageとAISense_Predictionは動作しない。
AIController側の場合は4つのAISenseは問題なく動作する。
ということがわかりました。