UE4
UnrealEngine

【UE4】AIPerceptionのDetect by Affiliationがブループリントのみで機能しない理由

More than 1 year has passed since last update.


はじめに

この記事は以下の記事に自分なりの補足を加えたものになります。


AI Perception in Unreal Engine 4 – How to Setup Written by Denis Rizov

https://denisrizov.com/2017/05/08/ai-perception-in-unreal-engine-4-how-to-setup/


リンク先の記事にはDetect by Affiliationを機能させるための手順が解説されていますので興味のある方は是非読んでいただければと思います。


Blueprintのみではチーム設定を行えない

現状(4.18.3)ではIGenericTeamAgentInterfaceが備える関数はBP側に公開されておらず、チーム設定を行うにはC++を避けられません。

ここではブループリントでチーム設定を行えない理由を説明します。


GenericTeamIdにメンバを設定ってノードあるよ?

ブループリントエディタで「GenericTeam」と検索すると以下のような候補が出ます。

2018-02-18_20h12_10.png

GenericTeamIdにメンバを設定というノードがあり、これを使えば問題なくTeamIDを設定できそうですが残念ながら実際には設定されません。

AIPerceptionがTeamIDを取得するための関数GetTeamIdentifierを呼び出すタイミングはBPのConstruction ScriptやBegin Playよりも前なのでBP側でノードが呼ばれるのは、TeamIDが取得された後なので意味を成しません。ですので、クラスのコンストラクタでTeamIDを設定する必要があります。


AIPerceptionがTeamIDを取得するまでの実行順

UAIPerceptionComponent::OnRegister



UAIPerceptionSystem::UpdateListener



FPerceptionListener::UpdateListenerProperties



UAIPerceptionComponent::GetTeamIdentifier



プレイヤーBPのインターフェースにGenericTeamAgentInterfaceってのが選べるけど?

BPのクラス設定を開くと「インターフェース」という項目があり追加ボタンから各種インターフェースを備える事が出来ます。

追加候補の中にGenericTeamAgentInterfaceというインターフェースがありますが、残念ながらこれを選択しても意味はありません。

恐らくですが、ここで候補として表示されるGenericTeamAgentInterfaceは関数GetGenericTeamIdとかが定義されているインターフェースクラスでは無い気がします。

GenericTeamAgentInterface.hには以下のようにインターフェースが2つあります。

UINTERFACE()

class AIMODULE_API UGenericTeamAgentInterface : public UInterface
{
GENERATED_UINTERFACE_BODY()
};

class AIMODULE_API IGenericTeamAgentInterface
{
GENERATED_IINTERFACE_BODY()
// 省略
};

候補として挙げられたGenericTeamAgentInterfaceはUInterfaceを継承したUGenericTeamAgentInterfaceではないかと思います。

本命のIGenericTeamAgentInterfaceにはAIPerceptionの刺激対象がどのチームに属するかを判定する関数GetTeamAttitudeTowardsがあります。

プレイヤーBPにGenericTeamAgentInterfaceを追加しても以下の矢印部分で失敗します。

    virtual ETeamAttitude::Type GetTeamAttitudeTowards(const AActor& Other) const

{
// ↓ NULLが返される(キャスト失敗)
const IGenericTeamAgentInterface* OtherTeamAgent = Cast<const IGenericTeamAgentInterface>(&Other);
以下省略
}


まとめ

FGenericTeamIdはUSTRUCTでブループリント側で触れるようになっていますがGenericTeamIdにメンバを設定ノードを呼び出しても実行順の関係で特に意味を成しませんし、BP側でGenericTeamAgentInterfaceを追加したとしても恐らくIGenericTeamAgentInterfaceでは無いのでキャストに失敗します。

これらの理由によりDetect by Affiliationをブループリントのみで機能させる事は出来ないと考えられます。

正直面倒ではありますがDetect by Affiliationで敵味方の判別をさせる際にはC++が必須です。幸いな事にC++での実装方法は記事上部にあるリンク先の記事にまとめられていますので、実装される方は是非読んでいただきたいと思います。