ゲームAI
UE4

【UE4】AISense_Sightの視線チェックを改良する

はじめに

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

AI Sight Perception to Custom Points WRITTEN BY Carlos Pardo
https://blog.gamedev.tv/ai-sight-perception-to-custom-points/

まずはリンク先の記事を読んでいただいてこちらを読むと理解しやすいと思います。

AISense_Sightの問題点

AISense_SightではAIが視認できているか否か(視線チェック)をLineTraceを用いてチェックしています。
しかし、この方法では少し問題が有り以下のような状況ではAIがプレイヤーを視認することが出来ません。
2017-11-17_22h49_51.png
両者はそれぞれ胸から上までさらけ出しているにも関わらずAIが視認出来ない理由はLineTraceの終了位置RootComponentの位置となってしまっているからです。
2017-11-17_22h50_59.png

最初の方に張った引用元記事ではこの問題を解決するためにAISightTargetInterfaceを継承しCanBeSeenFrom関数をオーバーライドしています。

CanBeSeenFromを更に改良してみる

引用元記事ではオーバーライドしたCanBeSeenFrom関数で

auto sockets = GetMesh()->GetAllSocketNames();

とすることでスケルタルメッシュが持つソケットを取得する様に書いていますがGetAllSocketNames関数はソケットに加えボーンまで取得されてしまいます。

C++ GetAllSocketNames returns bones along with sockets
https://answers.unrealengine.com/questions/726464/c-getallsocketnames-returns-some-bones-and-sockets.html

GetAllSocketNamesではIKボーンまで取得してしまいますので例えプレイヤーがしゃがんでいたとしても赤丸のIKボーンが見えていればAIには「見つけた」と判定されます。
2017-11-21_16h54_03.png
この問題を解決するために上記の引用リンクにあるように

GetActiveSocketList()

を利用します。

修正場所は1箇所だけです。

    //TArray<FName> sockets = GetMesh()->GetAllSocketNames();

    TArray<USkeletalMeshSocket*> sockets = GetMesh()->SkeletalMesh->GetActiveSocketList();

このようにGetAllSocketNames()をGetActiveSocketList()に置き換えるだけです。
GetActiveSocketList()ではUSkeletalMeshSocketを返しますから

#include "Engine/SkeletalMeshSocket.h"

このヘッダをインクルードすることを忘れないでください。

スケルタルメッシュにソケットを追加する

GetActiveSocketList関数を利用したことでゲーム中に使用するスケルタルメッシュにソケットを追加する必要があります。
自分は以下のように頭、腰、両肘、両手、両膝、両足首にソケットを追加しました。
2017-11-21_17h26_15.png

改良の結果

結果1 結果2 結果3 結果4
2017-11-17_23h14_24.png 2017-11-17_23h16_11.png 2017-11-17_23h16_54.png 2017-11-17_23h17_12.png

良い感じの結果が出ていますね。結果3や4は少しやり過ぎな気がしますが...
しかしこの方法のいいところはソケットの位置や追加場所を変更することでAIの視線チェックの位置を操作出来る所でしょう。
結果4のような結果が「理不尽だなぁ」と思われたのなら両足首のソケットを削除してしまえばOKです。

おわりに

引用元記事を書いてくださったCarlos Pardo氏には感謝です。色々と勉強になりました。