UE4
UnrealEngine

【UE4】AIPerceptionをAIControllerとCharacterにアタッチした時の違い

More than 1 year has passed since last update.


はじめに

過去に書いた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が付いている方にはそれぞれ以下のような処理を追加しました。

2018-02-25_00h03_34.png

2018-02-25_00h04_40.png


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_SightAISense_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は問題なく動作する

ということがわかりました。