Files
UE5-Modular-Game-Framework/docs/blueprints/09-ai/83_BPC_AIStateMachine.md
Lefteris Notas 411edea8ce add blueprints
2026-05-19 13:22:27 +03:00

180 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 61 — BPC_AIStateMachine
## Blueprint Spec — UE 5.55.7
---
### Parent Class
`ActorComponent`
### Dependencies
- [`BPC_AIControllerBase`](55_BPC_AIControllerBase.md) — Owner controller, blackboard access
- [`BPC_AlertSystem`](60_BPC_AlertSystem.md) — Alert level triggers state transitions
- [`BPC_PerceptionComponent`](56_BPC_PerceptionComponent.md) — Stimulus input
- [`BPC_BehaviorTreeManager`](57_BPC_BehaviorTreeManager.md) — Tree lifecycle requests
- [`BP_EnemyBase`](58_BP_EnemyBase.md) — Pawn animation state requests
- [`DA_AIProfile`](../12-content/63_DA_AIProfileDataAsset.md) — State timings, cooldowns, transition rules
### Purpose
High-level finite state machine for AI behavior. Manages valid state transitions, cooldowns, priority overrides, and lifecycle events for each AI state (Patrol, Investigate, Search, Combat, Flee, Idle, Stunned). Interprets alert level changes from the alert system and resolves transitions with rule checking before delegating to the behavior tree manager.
### Enums
| Enum | Values | Description |
|------|--------|-------------|
| `EAIState` | Idle, Patrol, Investigate, Search, Combat, Flee, Stunned, Dead | All possible AI states |
| `EStateTransitionRule` | Allow, Block (Cooldown), Block (Priority), Block (Health), Block (Narrative) | Transition permission results |
| `EStatePriority` | None, Low, Medium, High, Critical | State override priority |
### Structs
| Struct | Fields | Description |
|--------|--------|-------------|
| `FStateConfig` | State: EAIState, bCanTransitionFrom: Array<EAIState>, MinTimeInState: Float, MaxTimeInState: Float, CooldownAfterExit: Float, Priority: EStatePriority, bAllowInterrupt: Bool, AssociatedTree: EBehaviorTreeType | Configuration per state |
| `FStateInstance` | State: EAIState, EnterTime: Float, LastExitTime: Float, bIsActive: Bool, CustomData: FName (tag), bCanInterrupt: Bool | Runtime state tracking |
| `FTransitionRequest` | RequestedState: EAIState, Priority: EStatePriority, Reason: FName, Instigator: AActor | Queued transition |
### Variables
| Name | Type | Description |
|------|------|-------------|
| `CurrentState` | EAIState | Active state |
| `PreviousState` | EAIState | State before last transition |
| `StateMap` | Map<EAIState, FStateConfig> | All state configs from profile |
| `StateInstances` | Map<EAIState, FStateInstance> | Runtime state trackers |
| `PendingTransitions` | Array<FTransitionRequest> | Queue of requested transitions |
| `bIsTransitioning` | Bool | Lock during transition processing |
| `MaxTransitionsPerTick` | Int | Safety limit (default 3) |
| `bLockedByNarrative` | Bool | Story script lock |
| `NarrativeLockReason` | FName | Why narrative locked AI |
| `StunnedDuration` | Float | Current stun timer remaining |
| `FleeThreshold` | Float | Health % below which AI flees |
| `bCanFlee` | Bool | Permission to flee |
### Functions — Core
| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `RequestTransition` | NewState: EAIState, Priority: EStatePriority, Reason: FName, Instigator: AActor | Bool | Queue or execute state change |
| `ProcessPendingTransitions` | — | — | Evaluate queue on tick |
| `EvaluateTransitionRules` | FromState: EAIState, ToState: EAIState | EStateTransitionRule | Check if transition is allowed |
| `ForceTransition` | NewState: EAIState | — | Bypass rules (narrative/debug) |
| `GetCurrentState` | — | EAIState | BB getter |
| `GetTimeInCurrentState` | — | Float | Duration in current state |
| `CanTransitionTo` | NewState: EAIState | Bool | Public permission check |
| `IsStateActive` | State: EAIState | Bool | Check any state |
### Functions — State Lifecycle
| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `EnterState` | NewState: EAIState, Instigator: AActor | — | State entry logic |
| `ExitState` | CurrentState: EAIState | — | State exit cleanup |
| `UpdateState` | DeltaTime: Float | — | Per-tick state behavior |
| `OnStateEnter_Patrol` | — | — | Setup patrol BB keys |
| `OnStateEnter_Investigate` | Location: FVector | — | Setup investigation |
| `OnStateEnter_Search` | LastKnownLocation: FVector | — | Setup search area |
| `OnStateEnter_Combat` | Target: AActor | — | Combat initialization |
| `OnStateEnter_Flee` | ThreatLocation: FVector | — | Flee setup |
| `OnStateEnter_Stunned` | Duration: Float | — | Stun timer |
| `OnStateEnter_Idle` | — | — | Idle setup |
| `OnStateEnter_Dead` | — | — | Death state |
| `OnStateExit_All` | — | — | Common exit behavior |
### Functions — Transition Rules
| Name | Inputs | Outputs | Description |
|------|--------|---------|-------------|
| `CheckCooldown` | State: EAIState | Bool | Has cooldown expired |
| `CheckHealthThreshold` | ToState: EAIState | Bool | Health gate check for flee/stun |
| `CheckNarrativeLock` | — | Bool | Is AI locked by script |
| `CheckPriorityOverride` | Request: FTransitionRequest | Bool | Higher priority can interrupt |
| `CheckMinStateTime` | — | Bool | Minimum time in current state met |
### Blueprint Flow — Transition Resolution
```
[RequestTransition]
└─► If bLockedByNarrative AND not ForceTransition: deny (return false)
└─► If bIsTransitioning: queue to PendingTransitions, return false
└─► EvaluateTransitionRules:
Call CheckNarrativeLock --> if blocked, deny
Call CheckCooldown(FromState) --> if active, deny
Call CheckMinStateTime --> if not met, queue or deny
Call CheckPriorityOverride --> if request priority >= current, allow
Else: deny or queue
└─► If Allowed:
bIsTransitioning = true
ExitState(CurrentState)
EnterState(NewState)
Update blackboard
Request BehaviorTree switch from BT Manager
bIsTransitioning = false
Return true
[ProcessPendingTransitions]
└─► Sort PendingTransitions by Priority (high first)
└─► For each (up to MaxTransitionsPerTick):
Try RequestTransition again
If success: remove from queue
If fails again: increment failure counter, remove if > 3 attempts
[Event Tick]
└─► UpdateState(DeltaTime):
Switch CurrentState:
Patrol: Check patrol timer, check patrol completion
Investigate: Update investigation timer, check timeout
Search: Update search timer, check coverage
Combat: Update combat timer, check health for flee
Flee: Update flee timer, check distance from threat
Stunned: StunnedDuration -= DeltaTime; if <= 0, transition
Idle: Update idle timer
Check external triggers:
If bCanFlee && Health < FleeThreshold: RequestTransition(Flee)
If AlertSystem.IsInCombat && CurrentState != Combat: RequestTransition(Combat)
```
### State Transition Map (Allowed)
| From \ To | Idle | Patrol | Investigate | Search | Combat | Flee | Stunned | Dead |
|-----------|------|--------|------------|--------|--------|------|---------|------|
| Idle | — | Yes | Yes | No | Yes | No | Yes | Yes |
| Patrol | Yes | — | Yes | No | Yes | No | Yes | Yes |
| Investigate | Yes | Yes | — | Yes | Yes | No | Yes | Yes |
| Search | Yes | Yes | No | — | Yes | Yes | Yes | Yes |
| Combat | No | No | No | No | — | Yes | Yes | Yes |
| Flee | Yes | Yes | No | No | No | — | Yes | Yes |
| Stunned | Yes | Yes | Yes | No | Yes | Yes | — | Yes |
| Dead | No | No | No | No | No | No | No | — |
### Event Dispatchers
| Name | Delegate Signature | Purpose |
|------|-------------------|---------|
| `OnAIStateChanged` | EAIState NewState, EAIState PreviousState, AActor Instigator | For all listeners |
| `OnStateTransitionBlocked` | EAIState Requested, FStateTransitionRule Reason | Debug logging |
| `OnAIDefeated` | AActor Killer | Death sequence |
| `OnAIFled` | — | Flee started |
| `OnAIStunned` | Float Duration | Stun entered |
| `OnAIStateTimerWarning` | EAIState, Float RemainingTime | State expiry warning |
### Communications With
| Target | Method | Why |
|--------|--------|-----|
| [`BPC_AlertSystem`](60_BPC_AlertSystem.md) | Event listener | Alert level changes trigger transitions |
| [`BPC_BehaviorTreeManager`](57_BPC_BehaviorTreeManager.md) | Direct call | Request tree switch on state enter |
| [`BPC_AIControllerBase`](55_BPC_AIControllerBase.md) | Owner reference | Update BB keys |
| [`BP_EnemyBase`](58_BP_EnemyBase.md) | Event dispatcher | Trigger state animations |
| [`DA_AIProfile`](../12-content/63_DA_AIProfileDataAsset.md) | Data lookup | Load state configs |
| [`BPC_PerceptionComponent`](56_BPC_PerceptionComponent.md) | Direct call | Get stimulus for investigate |
| Narrative system | Event dispatcher | Narrative lock/unlock |
| [`BPC_HealthComponent`](../01-player/01_BPC_HealthComponent.md) | Event listener | Health threshold checks |
### Reuse Notes
- One per AIController; state configs defined per AI type in DA_AIProfile
- Priority queue prevents infinite loops during rapid state changes
- Narrative lock allows scripted moments where AI cannot react
- Stun state can be triggered by weapons, environment, or narrative events
- Flee uses the same path system as patrol (inverted direction)
- Dead state is terminal — no transitions out (death is hard finality by design for this horror framework)