【Unreal Engine】AI Perceptionで敵に見つけさせる:視覚と聴覚、見失ったあとの動き

作成: 2026-07-20

敵がプレイヤーに気づかない、壁越しに見つけてくる。UE5のAI Perceptionで視界と聴覚を設定し、On Target Perception Updatedで検知と見失いを受け取る方法を図解。見失った地点を5秒探して巡回へ戻る見張りを作る実践つき。

敵に巡回はさせられた。ところがプレイヤーが目の前を横切っても、まったく反応しません。設定を見直すうちに今度は逆になり、壁の向こうにいるはずのプレイヤーへ一直線に向かってきます。

UE5には、この「気づく」部分を専用に担当する AI Perception Component があります。距離と角度を自分で計算する必要も、視線を遮る壁のためにトレースを書く必要もありません。この記事では、視覚と聴覚の設定、検知と見失いの受け取り方、そして検知されない原因になりやすい設定を解説します。

扇形の視界に入った瞬間にプレイヤーへ気づく敵のイメージ

この記事でわかること

  • 感知は 見る側(AI Perception)見られる側(Stimuli Source) の組み合わせ
  • Sightの3つの半径と角度( Sight Radius / Lose Sight Radius / Peripheral Vision Half Angle
  • 検知されない原因は Detection by Affiliation のことが多い
  • 聴覚は Report Noise Event音を出す側 を作る
  • 実践: 見失った地点を5秒探して巡回へ戻る見張り

Sponsored

Behavior Treeとの役割分担

敵AIを作るとき、2つの仕組みが登場して混乱しがちです。担当は明確に分かれています。

仕組み担当ひとことで言うと
AI Perception周囲の状況を 感じ取る気づくか
Behavior Tree感じ取った結果をもとに 行動を選ぶ何をするか
Blackboard2つをつなぐ 記憶覚えておくこと

AI Perceptionは行動を一切決めません。 「このActorが見えた」「見えなくなった」を知らせるだけ です。それを受けてBlackboardへ書き込み、Behavior Treeがその値を見て枝を選びます。

この記事は感知の側に集中します。木の組み方そのものは Behavior Treeの記事 を先に読むと、実践がそのまま続きになります。

見る側と、見られる側

感知は 2つの部品が揃って 成立します。片方だけでは何も起きません。

左に視界を持つAI Controller、右に感知される対象があり、両方が揃って検知が成立することを示す図
部品付ける先役割
AI Perception ComponentAI Controller感じ取る側。視覚や聴覚の設定を持つ
AI Perception Stimuli Source Component感知される側のActor「ここに感知できるものがある」と登録する

AI Perception ComponentはPawnにも付けられますが、 AI Controllerに付けるのが標準 です。Pawnが入れ替わってもAIの判断はController側に残るためです。

見られる側については、1つ知っておくべき仕様があります。 Pawn(Characterを含む)は自動でソースとして登録されます。 そのため、ThirdPersonのプレイヤーキャラクターを検知させるだけなら、Stimuli Sourceコンポーネントは要りません。

必要になるのは、 Pawnではない普通のActor を感知させたいときです。壊れる樽、落ちている装備、光る目印などがこれにあたります。この場合はコンポーネントを追加し、詳細パネルで設定します。

項目設定
Auto Register as Sourceチェックを入れる
Register as Source for Senses配列に AISense_Sight を追加(聴覚なら AISense_Hearing

Register as Source for Senses は既定で空です。 ここが空のままだと、コンポーネントを付けても何の感覚にも登録されず、永遠に検知されません。Pawn以外を感知させたいのに反応しないときは、まずここを見てください。

Sponsored

Sightの設定:どこまで、どの角度で見えるか

AI Controllerの AIPerception を選び、詳細パネルの Senses ConfigAI Sight config を追加します。ここが視界の本体です。

Sight RadiusとLose Sight Radiusの同心円に、Peripheral Vision Half Angleの扇形が重なった俯瞰図
項目意味
Sight Radius見つけられる 距離。この外側からは発見できない
Lose Sight Radius見失う 距離。 Sight Radiusより大きく する
Peripheral Vision Half Angle正面からの 片側 の角度(度)。既定は 90 で、視野は前方180度
Auto Success Range from Last Seen Location一度見た相手が この距離以内なら、遮蔽や角度を無視して見え続ける 。既定は -1.0 で無効
Max Age感知した情報が保持される秒数。0 は期限なし

半径を2つ持たせているのは、 境界線上でのちらつきを防ぐため です。1つしかないと、その距離を挟んで往復するプレイヤーに対して「発見」と「見失い」が高速で交互に起きます。 Sight Radius 1200 / Lose Sight Radius 1600 のように 見失う側を広く すると、一度見つけた相手にはしつこく食い下がるAIになります。

Peripheral Vision Half Angle は半分の角度 である点に注意してください。 60 と入れると視野は左右合わせて120度です。90を入れると180度、つまり真横までは見える設定になります。

視界を遮る判定は自動で行われます。AIとターゲットの間に線が引かれ、遮られていれば見えていない扱いになります。この判定に使うチャンネルは Project Settings > Engine > AI SystemDefault Sight Collision Channel (既定は Visibility )です。 壁越しに見つけてくる ときは、その壁のCollisionがこのチャンネルをBlockしているかを確認してください(→ Collisionプロファイルの記事)。

検知されない最大の原因

設定を正しく入れたのに何も起きない。この原因のほとんどが Detection by Affiliation です。

Detect Enemies だけが有効な既定状態では、中立扱いのBlueprintが検知されないことを示す図

AI Sight configの中にある3つのチェックボックスで、 どの陣営を感知するか を決めます。

項目既定意味
Detect Enemiesオン敵対しているものを感知する
Detect Neutralsオフ中立のものを感知する
Detect Friendliesオフ味方を感知する

そして重要なのが、 陣営(Team)の判定方法 です。UEは IGenericTeamAgentInterface を実装したActorをチーム付きとして扱いますが、これは標準ではBlueprintから設定できません。

結果として、 Blueprintだけで作ったActorは、すべて中立として扱われます 。既定では Detect Neutrals がオフなので、 視界に入っても何も起きない というわけです。

Blueprintで検証する段階では、 Detect Neutrals にチェックを入れてください。 これだけで動き出します。

ただし、そのままでは 敵同士も互いを検知します 。プレイヤーだけを狙わせたいなら、感知したActorを受け取ったあとで Tagやクラスで絞り込む 必要があります。次の節で扱います。

Sponsored

検知と見失いを受け取る

AI Perception Componentの詳細パネル下部から On Target Perception Updated イベントを追加します。 感知の状態が変わった瞬間だけ 呼ばれるイベントです。

ピンは2つです。

ピン内容
ActorActor状態が変わった相手
StimulusAIStimulus(構造体)何が起きたかの詳細

Stimulus は構造体なので、 Break AIStimulus で中身を取り出します。よく使うのは3つです。

メンバ内容
Successfully Sensedtrue なら 感知したfalse なら 見失った
Stimulus Location感知した対象があった座標。 見失ったときは、最後に確認できた位置 が入る
Tag刺激に付けられた名前。Report Noise Event で指定できる

つまり、このイベント1つで 発見と見失いの両方 が届きます。

On Target Perception Updatedという1つのイベントがSuccessfully Sensedで分岐し、trueなら追いかける、falseなら最後に見た地点へ向かうことを示す図
Event On Target Perception Updated(Actor, Stimulus)
  → Break AIStimulus(Stimulus)
  → Branch(Condition: Successfully Sensed)
      True  → (見つけた)
      False → (見失った。Stimulus Location が最後に見た位置)

Stimulus Location が「最後に見た位置」として使えるのが便利なところです。見失った瞬間に別途トレースを飛ばす必要はありません。

聴覚は「音を出す側」を作る

視覚と違い、聴覚は 鳴らすだけでは伝わりません 。スピーカーから出ている音とAIが聞き取る音は、まったく別の仕組みだからです(→ 3Dサウンドの記事)。

足音の発生地点から同心円状にノイズが広がり、範囲内のAIだけが反応することを示す図

聞く側は Senses ConfigAI Hearing config を追加します。

項目意味
Hearing Range聞こえる距離
Detection by AffiliationSightと同じ。 ここでも Detect Neutrals が要る

出す側は Report Noise Event ノードを呼びます。足音、銃声、物を壊した音など、AIに気づかせたいタイミングで実行します。

引数意味
Noise Location音が鳴った座標
Loudness音の大きさの倍率。届く距離に掛かる
Instigator音を出したActor 。AIはこのActorを感知対象として受け取る(省略不可)
Max Range届く上限距離。0 なら聞く側の Hearing Range に任せる
Tagこの音に付ける名前
(走っている間、足が着くたびに)
  → Report Noise Event(Noise Location: 自分の位置, Loudness: 1.0,
                        Instigator: self, Max Range: 0.0, Tag: "Noise")

Instigator を必ず入れてください。 ここが空だと、聴覚イベントとして正しく処理されないことがあります。「誰の音か不明のまま届く」のではなく、 そもそも届かない と考えて、必ず音を出した本人を渡してください。

Tag を付けておくと、受け取り側で 視覚と聴覚を区別できます 。視覚で感知した刺激のTagは空なので、 Tag == "Noise" かどうかで分岐すれば「見えた」と「聞こえた」を別扱いにできます。実践ではこれを使います。

補足: Actorには Make Noise というノードもあり、こちらにも LoudnessTag の指定はあります。ただし旧来の Pawn Noise Emitter / Pawn Sensing との互換を含む仕組みで、経路が分かりにくくなります。 AI Perceptionへ直接届けるなら Report Noise Event の方が素直です。

Sponsored

実践:見失った地点を5秒探す見張りを作る

ステルスゲームの警備員、ホラーゲームの徘徊者、アクションRPGのフィールドモンスター。 「見つけたら追い、見失ったら最後にいた場所を調べ、諦めて巡回に戻る」 は、ジャンルを問わず敵AIの標準的な振る舞いです。

見つけた瞬間に追いかけるだけのAIは、物陰に入られた途端に何事もなかったかのように巡回へ戻ります。この「調べる時間」があるかどうかで、AIの手応えは大きく変わります。

完成形

巡回中の敵が視界に入ったプレイヤーを追い、柱の陰で見失うと最後の地点まで来て5秒うろつき、巡回へ戻る流れの図

敵は範囲内を巡回し、正面120度・12m以内にプレイヤーが入ると追いかけてきます。柱の陰に隠れると、 最後にプレイヤーが見えた地点の付近まで歩いてきて5秒とどまり 、それから巡回へ戻ります。

5秒は 到着してから の待ち時間です。移動時間を含めて5秒ではありません。また Acceptable Radius: 100 を指定しているので、地点ちょうどではなく1m以内で停止します。

再現条件

Third Person テンプレート で新規プロジェクトを作ります。

前提: この実践は Behavior Treeの記事 の構成を土台にしています。巡回だけをする敵(BTT_FindPatrolLocation を含む)が動く状態から始めてください。ここでは 「気づく枝」を足す部分だけ を扱います。

BlackboardとBehavior Treeはコンテンツブラウザの右クリック → Artificial Intelligence から作成できます。

種類名前設定
CharacterBP_EnemyAI Controller ClassBP_EnemyAIControllerAuto Possess AIPlaced in World(実行中にスポーンもするなら Placed in World or Spawned
AIControllerBP_EnemyAIControllerAIPerception Componentを追加
BlackboardBB_EnemyKeyを3つ(下表)
Behavior TreeBT_EnemyBlackboard AssetBB_Enemy
BTTaskBTT_ClearLastKnownBlueprint ClassAll ClassesBTTask_BlueprintBase を選んで作成(Artificial Intelligenceメニューからは作れません)
レベルNav Mesh Bounds Volume床を覆うサイズに。 P を押して緑になることを確認
レベル柱や壁のStatic Mesh視界を遮るもの。 Collisionが Visibility をBlockすること
プレイヤーBP_ThirdPersonCharacterActor Tag に Player を追加

聴覚の動作も確かめるなら、プレイヤー側から音を出す処理が要ります。動作確認用に、BP_ThirdPersonCharacter のイベントグラフへ次を足しておくと簡単です。

N(Keyboard Event)
  → Report Noise Event(Noise Location: Get Actor Location, Loudness: 1.0,
                        Instigator: self, Max Range: 0.0, Tag: "Noise")

これで N キーを押した位置に音が発生します。足音に連動させる場合は、Animation Notifyから同じノードを呼びます。

Blackboardのキーは3つです。

Key名初期値用途
TargetActorObject(Base Class: Actor)追いかける相手
LastKnownLocationVector最後に見た地点
PatrolLocationVector次の巡回地点

ステップ1:視覚と聴覚を設定する

BP_EnemyAIControllerAIPerception を選び、Senses Config に2つ追加します。

AI Sight config

項目
Sight Radius1200.0(12m)
Lose Sight Radius1600.0
Peripheral Vision Half Angle60.0視野120度
Auto Success Range from Last Seen Location-1.0(無効のまま)
Detect Neutralsチェック

AI Hearing config

項目
Hearing Range2000.0(20m)
Detect Neutralsチェック

Detect Neutrals2つとも 必要です。片方だけ入れて「音には反応するのに見えていない」と悩むパターンがよくあります。

ステップ2:検知を受け取ってBlackboardへ書く

BP_EnemyAIController のイベントグラフに On Target Perception Updated を追加し、次を組みます。ここがこの記事の中心です。

On Target Perception UpdatedからTag判定・音か視覚かの分岐を経て、TargetActorとLastKnownLocationを書き分けるノードグラフ
Event On Target Perception Updated(Actor, Stimulus)
  → Break AIStimulus(Stimulus)→ Successfully Sensed / Stimulus Location / Tag
  → Actor Has Tag(Target: Actor, Tag: "Player")
  → Branch
      False → (何もしない)                          ← プレイヤー以外は無視
      True  → Branch(Condition: Tag == "Noise")
          True  → Branch(Condition: Successfully Sensed)
              True → Set Value as Vector(Key Name: LastKnownLocation)  ← 【聞こえた】
                       (Key: LastKnownLocation, Value: Stimulus Location)
          False → Branch(Condition: Successfully Sensed)
              True  → Set Value as Object(Key Name: TargetActor)    ← 【見つけた】
                        (Key: TargetActor, Object: Actor)
              False → Branch(Condition: Actor == Get Blackboard Value as Actor(TargetActor))
                  True → Set Value as Vector(Key Name: LastKnownLocation) ← 【見失った】
                           (Key: LastKnownLocation, Value: Stimulus Location)
                       → Clear Value(Key Name: TargetActor)

書き分けが3通りある点が肝です。

  • 見つけた: TargetActor に相手を入れる。追跡が始まります
  • 見失った: 先に LastKnownLocation最後の座標を保存してから TargetActor をクリアします。順番が逆だと、追跡が止まったのに探す場所が無い状態になります
  • 聞こえた: LastKnownLocation だけを書き、 TargetActor は触りません。 音では姿が見えていない ので、直接追跡させないのが自然な挙動です

聴覚側でも Successfully Sensed を確認しているのは、 刺激が期限切れになったときにも通知が来る ためです。ここを省くと、古い音の位置へ何度も向かってしまいます。

見失いの判定に Actor == TargetActor を挟んでいるのは、 無関係なActorを見失っただけでターゲットが消えるのを防ぐ ためです。

ここで使うノードには2系統あるので注意してください。

使う場所ノードキーの指定
AI Controller から操作するSet Value as Object / Set Value as Vector / Clear ValueKey Name(文字列)
BTTask Blueprint の中で操作するSet Blackboard Value as ... / Clear Blackboard ValueBlackboard Key Selector 変数

今回はAI Controllerに書くので 前者 を使います。Target ピンには Get Blackboard の戻り値をつなぎます。ここが空だと、エラーは出ないまま何も書き込まれません。

検索欄に「Set Blackboard Value」と打つと後者が先に出てくるので、 Target ピンが Blackboard Component になっているか を必ず確認してください。

木の起動も忘れずに置きます。

Event On Possess(BP_EnemyAIController)
  → Run Behavior Tree(BTAsset: BT_Enemy)

ステップ3:探す枝をBehavior Treeに足す

BT_Enemy3本の枝 にします。 左が優先 です。

ルートSelectorの下に追跡・調査・巡回の3つのSequenceが並んだBehavior Treeの図
Root
└─ Selector
   ├─ Sequence 「追う」
   │   ⚑ Decorator: Blackboard(TargetActor is Set / Observer aborts: Both)
   │   └─ Task: Move To(Blackboard Key: TargetActor, Acceptable Radius: 200)
   │
   ├─ Sequence 「最後の地点を調べる」
   │   ⚑ Decorator: Blackboard(LastKnownLocation is Set / Observer aborts: Both)
   │   ├─ Task: Move To(Blackboard Key: LastKnownLocation, Acceptable Radius: 100)  ← 地点ちょうどではなく1m以内で停止
   │   ├─ Task: Wait(Wait Time: 5.0)          ← ここが「5秒探す」
   │   └─ Task: BTT_ClearLastKnown              ← 調べ終わったので忘れる
   │
   └─ Sequence 「巡回する」
       ├─ Task: BTT_FindPatrolLocation
       ├─ Task: Move To(Blackboard Key: PatrolLocation)
       └─ Task: Wait(Wait Time: 2.0)

真ん中の枝が今回の追加分です。 BTT_ClearLastKnown を最後に置くのが重要 で、これが無いと LastKnownLocation が残り続け、敵は同じ地点を延々と往復します。

BTT_ClearLastKnown の中身は3ノードです。

変数: TargetKey(Blackboard Key Selector型・Instance Editable)

Event Receive Execute AI
  → Clear Blackboard Value(Key: TargetKey)
  → Finish Execute(Success: true)

Behavior Tree上でこのTaskを選び、詳細パネルの Target KeyLastKnownLocation を割り当てます。

BTT_FindPatrolLocationBehavior Treeの記事 と同じもので、Get Random Reachable Point in Radius で地点を求めて PatrolLocation へ書くTaskです。

Decoratorの Observer abortsBoth にしておくのを忘れないでください。これが None だと、巡回のWaitが終わるまでプレイヤーの発見に反応しません。

確認する

BP_Enemy をレベルに配置してPlayし、次を順に試します。

  1. 敵の背後から近づく。 12m以内でも 反応しません 。視野は前方120度なので、真後ろは見えていません
  2. 正面へ回り込む。 12m以内に入った瞬間、敵が 巡回をやめてこちらへ向かってきます
  3. 柱の陰へ入る。 敵は プレイヤーが最後に見えた地点まで歩いてきて、そこで5秒とどまり 、その後ランダムな巡回に戻ります
  4. 5秒のあいだに柱の反対側から顔を出す。 再び発見され、追跡が始まります

Behavior Treeを開いたままPlayすると、実行中のノードが光り、 BlackboardパネルTargetActorLastKnownLocation の中身を追えます。値が入る瞬間と消える瞬間を見ると、どこで止まっているかがすぐ分かります。

うまくいかないときの切り分けです。

  • 視界に入っても何も起きないDetect Neutrals が未チェック。最初に疑うのはここです
  • Blackboardの TargetActor が空のまま → プレイヤーのActor Tagが Player になっていない、または綴り違い
  • 壁越しに見つけてくる → その壁のCollisionが Visibility チャンネルをBlockしていません
  • 真後ろからでも見つかるPeripheral Vision Half Angle が既定の 90(視野180度)のまま
  • 見失っても追い続けるLose Sight Radius が大きすぎるか、Auto Success Range from Last Seen Location に値を入れています
  • 同じ地点を往復し続けるBTT_ClearLastKnown が抜けているか、Target Key が未割り当て
  • 敵同士で追いかけ合う → Tag判定を通していません
  • そもそも動かない → Nav Mesh Bounds Volume(P で確認)と Auto Possess AI

動きが見えたら、 Auto Success Range from Last Seen Location400 を入れて 試してみてください。一度見つかると、4m以内では柱の陰に入っても見え続けるようになります。「一度気づかれたら、近くでは隠れきれない」という詰めの緊張感は、この1項目で作れます。

ポイントは2つです。

  • 感知の結果は、必ずBlackboardの値に翻訳する: AI Perceptionから直接キャラクターを動かすと、Behavior Treeの判断と二重管理になります。 Perceptionは書くだけ、行動を決めるのは木だけ に分けておくと、あとから枝を足しても壊れません
  • 「見えた」と「聞こえた」を同じ扱いにしない: 音は姿を捉えていないので、TargetActor ではなく LastKnownLocation に落とします。この区別があるだけで、AIは「物音のした方を見に行く」という自然な動きになります

追う速度や攻撃までの間合いを詰めていく段階になったら NavMeshの設定 を、視界を自前で作る方法と比べたくなったら Line Traceの記事 を参照してください。

Sponsored

おまけ:先に知っておくと良いこと

検知したら音楽を変える。 On Target Perception Updated は、敵の行動だけでなく BGM の切り替えにも使えます。検知で戦闘レイヤーを重ね、見失ったら戻す、という演出が変数1つで作れます(→ インタラクティブミュージック)。

設定した視界を、実際に目で見る。 Sight RadiusPeripheral Vision Half Angle の数値がゲーム世界のどこまでなのかは、描いてみないと分かりません。Draw Debug SphereDraw Debug Cone を足すか、Visual Loggerで巻き戻すと一発です(→ Draw DebugとVisual Logger)。

  • Gameplay Debuggerで視界を目で見る: Play中に '(アポストロフィ) を押すとGameplay Debuggerが開き、数字キーでカテゴリを切り替えられます。Perceptionのカテゴリを表示すると、視界の範囲と感知中の対象がビューポートに描かれます。数値を推測で調整する前に、まず見てください(→ デバッグ表示の記事
  • Dominant Sense は「問い合わせたときの優先感覚」: AISense_Sight を指定すると、Perception Componentに対象の位置を尋ねたときに視覚の情報が優先されます。ただし、今回のように イベントごとに Stimulus Location を自分でBlackboardへ書く作りでは、この設定は効きません 。書き込む側で優先順位を決める必要があります
  • Max Age は用途で変える: 感知情報が保持される秒数です。0 は期限なしを意味します。「数秒で忘れてほしい」なら短く、「一度気づいたら覚えていてほしい」なら長くします
  • Damageの感覚もある: AI Damage sense config を追加すると、背後から撃たれたときに反応させられます。ダメージ側で Report Damage Event を呼ぶ必要があります(→ ダメージ処理の記事
  • 見る側と見られる側で基準が違う: 見る側(AI)の視点は Get Actor Eyes View Point に基づく位置と向きが使われます。一方、見られる側は既定でActorの位置が基準です。しゃがみや遮蔽を厳密に扱いたい場合は、見られる側に IAISightTargetInterface を実装して判定点を指定します
  • チーム分けをきちんとやるならC++が要る: IGenericTeamAgentInterface の実装はBlueprintだけでは完結しません。敵・味方・中立を本格的に分けたくなったら、C++でAI Controllerに実装するのが定石です(→ C++への第一歩

まとめ

AI Perceptionは、設定項目こそ多いものの、押さえる骨格は少数です。

要素役割
AI Perception ComponentAI Controllerに付ける。感じ取る側
Stimuli Source Component感知される側に付ける。 Pawnは自動登録されるので不要
AI Sight config距離2つ(Sight / Lose Sight)と半角の角度
AI Hearing config距離。鳴らす側は Report Noise Event
Detection by Affiliation既定はDetect Enemiesのみ。BPで検証するなら Detect Neutrals
On Target Perception Updated発見と見失いの両方が届く。Successfully Sensed で分ける

そして設計の指針が1つ。 Perceptionは書き込むだけ、行動はBehavior Treeが決める ことです。この境界を守っておけば、「隠れているプレイヤーを探す」「仲間に知らせる」といった振る舞いを足すとき、触るのは木の側だけで済みます。

あなたのゲームの敵は、プレイヤーを見失ったあと、どのくらい粘ってほしいですか。