Threat Detection

Documentation Unreal Engine AI Threat Detection

Track player camera attention and react when being observed.


The AI knows when you're watching, and changes behavior accordingly.

Interactive Threat Detection

Aim with your mouse (Vision Cone)
Looking at an enemy increases their Threat. High Threat = Aggro.

When to Use This

  • Soulslike games where enemies react to player attention
  • Stealth/horror games with awareness mechanics
  • Dynamic difficulty that punishes passive observation
  • Any AI that should behave differently when the spotlight is on them
This component can be used independently of the other plugin systems.

Core Concepts

How It Works

The component checks if the player's camera is pointing at the AI:
Player Camera
      \
       \  < 15° (configurable)
        \
         ↘ [AI]  ← "I'm being watched!"
When the player looks at the AI:
  1. Threat level starts accumulating (0.0 → 1.0)
  2. The longer they stare, the higher the threat
  3. When threat reaches threshold, the AI reacts
When the player looks away:
  • Threat level decays over time back to 0

Threat Level

A normalized value from 0.0 to 1.0:
ValueMeaning
0.0Not observed at all
0.0 - 0.5Casually glanced at
0.5 - 0.8Player is watching
0.8 - 1.0Player is staring
Use this value to:
  • Modify action scores (defensive actions score higher when threatened)
  • Trigger strafe direction changes
  • Enable/disable certain behaviors

Quick Setup

The component is automatically added to AEnemyControllerBase. For custom AI controllers, add ThreatDetectionComponent in the Components panel.

Threat Response Wiring

The SECCombatControllerComponent automatically wires threat responses if both ThreatDetectionComponent and MovementEvaluatorComponent are present on the controller.
On SECCombatControllerComponent (wiring toggle):
PropertyDefaultPurpose
bEnableThreatDetectiontrueEnable threat detection on BeginPlay
On MovementBehaviorProfile (per-role behavior - switches automatically with combat role):
PropertyDefaultPurpose
bSwapStrafeOnHighThreatfalseSwap strafe direction when threat duration is exceeded
bAdjustDistanceByThreatfalseAdjust movement distance multiplier based on threat
ThreatDistanceScale1.0Scale factor for distance adjustment: 1.0 + ThreatLevel * Scale
Because threat response settings live on the movement profile, they automatically change when the AI switches combat roles. A cautious "Waiter" role can react to threat with distance adjustments, while an aggressive "Attacker" profile ignores threat entirely. No per-AI configuration needed.

Configure Thresholds

In your AI Controller Blueprint → ThreatDetectionComponent:
PlayerLookAngleThreshold = 15.0f;   // Degrees - how directly must player look
PlayerLookTimeThreshold = 3.0f;     // Seconds to reach max threat

Read Threat Level

// In StateTree, Blueprint, or C++:
float Threat = ThreatDetection->GetCurrentThreatLevel();
 
if (Threat > 0.7f)
{
    // Player is really staring - do something about it
}

Key Properties

PropertyDefaultPurpose
PlayerLookAngleThreshold15.0°How directly player must look to trigger
PlayerLookTimeThreshold3.0sTime to reach max threat
ThreatDecayRate0.5How fast threat drops when not observed
bEnabledtrueToggle detection on/off

Key Functions

// Current threat level [0.0 - 1.0]
float GetCurrentThreatLevel() const;
 
// Is player actively looking at this AI right now?
bool IsPlayerLookingAtMe() const;
 
// Enable/disable detection
void SetThreatDetectionEnabled(bool bEnabled);
 
// Reset threat to zero
void ResetThreat();

Usage Examples

Strafe Direction Swap

The SECCombatControllerComponent automatically handles strafe swaps when threat duration is exceeded. Enable bSwapStrafeOnHighThreat on the component:
// Configured via SECCombatControllerComponent properties:
// bSwapStrafeOnHighThreat = true
// When OnThreatDurationExceeded fires, MovementEvaluator->SwapStrafeSide() is called automatically
No extra code needed if you're using SECCombatControllerComponent with both ThreatDetectionComponent and MovementEvaluatorComponent.
To also adjust distance based on threat, enable bAdjustDistanceByThreat:
// Distance multiplier formula: 1.0 + ThreatLevel * ThreatDistanceScale
// At ThreatLevel = 0.8 with ThreatDistanceScale = 1.0 → multiplier = 1.8
// AI backs away further when the player is staring

Defensive Action Bonus

Modify action scores based on threat:
// In your action scoring (or use context modifiers):
float ThreatBonus = ThreatDetection->GetCurrentThreatLevel();
DefensiveAction.RuntimeScoreBonus = ThreatBonus * 0.5f;  // Up to +50% when threatened

"I See You" Bark

Trigger audio/visual feedback:
void OnThreatLevelChanged(float OldThreat, float NewThreat)
{
    if (OldThreat < 0.5f && NewThreat >= 0.5f)
    {
        PlayBarkSound("ISeeYou");
    }
}

Debug Tools

Enable Logging:
ThreatDetection->bDebugLog = true;
Console Command:
SEC.Debug.Threat.DrawDetection 1   // Visualize detection cone

Integration Points

SystemHow Threat Detection Connects
Movement SystemSECCombatControllerComponent auto-wires strafe swap and distance adjustment based on threat
Action SystemThreat level can boost defensive action scores
Combat RolesThreatened AI may be deprioritized for Attacker role