- Updated `CONTEXT.md` to reference the new Manual Implementation Guide and Build Checklist in blueprint spec files. - Added a detailed Manual Implementation Guide to `01_GI_GameTagRegistry.md`, including class setup, variable initialization, function implementations, and a build checklist. - Introduced a Manual Implementation Guide section in `22_BPC_PhysicsDragSystem.md` with step-by-step instructions for setup and function logic. - Expanded `28_BPC_ConsumableSystem.md` with a comprehensive Manual Implementation Guide detailing class setup, variable initialization, function implementations, and networking. - Enhanced `69_BP_WeaponBase.md` with a Manual Implementation Guide covering class setup, variable defaults, function implementations, and networking. - Added a Manual Implementation Guide to `84_AI_BaseAgentController.md`, outlining class setup, variable initialization, function implementations, and networking. - Updated `TEMPLATE.md` to version 2.0, incorporating the Manual Implementation Guide and Build Checklist for human implementers. - Revised `INDEX.md` to reflect the new purpose and content of blueprint specifications, emphasizing the inclusion of the Manual Implementation Guide.
362 lines
14 KiB
Markdown
362 lines
14 KiB
Markdown
# AI_BaseAgentController — AI Controller
|
||
|
||
## Blueprint Spec — UE 5.5–5.7
|
||
|
||
---
|
||
|
||
### Parent Class
|
||
`AIController`
|
||
|
||
### Dependencies
|
||
- [`BP_EnemyBase`](58_BP_EnemyBase.md) — Pawn
|
||
- [`BPC_AIPerceptionSystem`](BPC_AIPerceptionSystem.md) — Sensing
|
||
- [`BB_AgentBoard`](BB_AgentBoard.md) — Decision-making
|
||
- [`BPC_AIStateMachine`](61_BPC_AIStateMachine.md) — High-level states
|
||
- [`BPC_AlertSystem`](60_BPC_AlertSystem.md) — Threat awareness
|
||
- [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) — Self health
|
||
- [`I_Damageable`](../01-core/03_I_InterfaceLibrary.md) — Damage reception
|
||
- `DA_AIProfile` — AI configuration
|
||
|
||
### Purpose
|
||
Central brain for enemy AI characters. Manages perception, decision-making via Behavior Trees, high-level state machine transitions, alert level propagation, and combat coordination. Possesses `BP_EnemyBase` pawns and controls their actions through Blackboard values and Behavior Tree execution.
|
||
|
||
### Variables
|
||
|
||
| Name | Type | Description |
|
||
|------|------|-------------|
|
||
| `AIProfile` | DA_AIProfile | Configuration asset |
|
||
| `PossessedEnemy` | BP_EnemyBase | Current pawn reference |
|
||
| `BlackboardComp` | UBlackboardComponent | Blackboard instance |
|
||
| `BehaviorTreeComp` | UBehaviorTreeComponent | Behavior tree runner |
|
||
| `PerceptionComp` | BPC_AIPerceptionSystem | Sensory input |
|
||
| `StateMachine` | BPC_AIStateMachine | State logic |
|
||
| `AlertSystem` | BPC_AlertSystem | Threat level |
|
||
| `bIsActive` | Bool | Enabled / disabled |
|
||
| `AggressionRange` | Float | Engage distance |
|
||
| `SuspicionRange` | Float | Investigate distance |
|
||
| `CombatRange` | Float | Preferred combat distance |
|
||
| `HomeLocation` | FVector | Spawn or patrol anchor |
|
||
| `LastKnownPlayerLocation` | FVector | Blackboard updated |
|
||
| `bHasLineOfSight` | Bool | LOS status |
|
||
| `LostPlayerTimer` | Float | Seconds since last sighting |
|
||
|
||
### Blackboard Keys
|
||
|
||
| Key Name | Type | Description |
|
||
|----------|------|-------------|
|
||
| `SelfActor` | Object | Self reference |
|
||
| `TargetActor` | Object | Current threat |
|
||
| `TargetLocation` | Vector | Last known threat location |
|
||
| `HomeLocation` | Vector | Patrol anchor |
|
||
| `AIState` | Enum (EAIState) | Current state |
|
||
| `AlertLevel` | Float | 0.0–1.0 awareness |
|
||
| `bHasLOS` | Bool | Line of sight |
|
||
| `bIsInvestigating` | Bool | Searching location |
|
||
| `PatrolIndex` | Int | Current waypoint |
|
||
| `CombatStance` | Enum | Aggressive / Defensive |
|
||
| `StimulusLocation` | Vector | Sound/sight trigger point |
|
||
|
||
### Enums
|
||
|
||
| Enum | Values | Description |
|
||
|------|--------|-------------|
|
||
| `EAIState` | Idle, Patrol, Suspicious, Alerted, Combat, Searching, Fleeing, Disabled | AI behavior state |
|
||
|
||
### Functions
|
||
|
||
| Name | Inputs | Outputs | Description |
|
||
|------|--------|---------|-------------|
|
||
| `OnPossess` | Pawn: APawn | — | Bind blackboard, run BT |
|
||
| `OnUnPossess` | — | — | Cleanup |
|
||
| `InitializeAI` | Profile: DA_AIProfile | — | Set up components |
|
||
| `SetAIState` | NewState: EAIState | — | State machine transition |
|
||
| `UpdatePerception` | Stimulus: FAIStimulus | — | Process sensory input |
|
||
| `SetTarget` | Target: AActor | — | Update blackboard target |
|
||
| `ClearTarget` | — | — | Target lost |
|
||
| `StartInvestigation` | Location: FVector | — | Move to investigate |
|
||
| `RequestReinforcements` | — | — | Alert nearby allies |
|
||
| `GetCombatReadiness` | — | Float | Based on health, ammo, alert |
|
||
| `OnTakeDamage` | DamageResult: FDamageResult | — | React to being hit |
|
||
| `CanSeeTarget` | — | Bool | LOS check |
|
||
| `LostSightOfTarget` | — | — | Start search timer |
|
||
| `ReturnToPatrol` | — | — | Reset to patrol state |
|
||
| `GetHomeLocation` | — | FVector | Patrol anchor |
|
||
| `SetFocalPoint` | Location: FVector | — | Aim facing direction |
|
||
|
||
### Event Dispatchers
|
||
|
||
| Name | Parameters | Fired When |
|
||
|------|-----------|-----------|
|
||
| `OnAIStateChanged` | OldState: EAIState, NewState: EAIState | State transition |
|
||
| `OnTargetAcquired` | Target: AActor | New threat detected |
|
||
| `OnTargetLost` | — | Target out of range/perception |
|
||
| `OnAlertRaised` | AlertLevel: Float | Alert threshold crossed |
|
||
| `OnReinforcementRequested` | Location: FVector | Call for backup |
|
||
|
||
### Blueprint Flow
|
||
|
||
```
|
||
[OnPossess]
|
||
└─► PossessedEnemy = Cast<BP_EnemyBase>(Pawn)
|
||
└─► AIProfile = PossessedEnemy.AIProfile (or set from spawner)
|
||
└─► InitializeAI(AIProfile)
|
||
└─► RunBehaviorTree(AIProfile.BehaviorTree)
|
||
└─► SetHomeLocation(Pawn.GetActorLocation)
|
||
|
||
[InitializeAI]
|
||
└─► Create BPC_AIPerceptionSystem if not exists
|
||
└─► Create BPC_AIStateMachine
|
||
└─► Create BPC_AlertSystem
|
||
└─► PerceptionComp.Initialize(AIProfile.PerceptionConfig)
|
||
└─► StateMachine.Initialize(EAIState.Patrol)
|
||
└─► AlertSystem.Initialize()
|
||
└─► Set AIState = Patrol in Blackboard
|
||
|
||
[UpdatePerception — called by PerceptionComp dispatcher]
|
||
└─► If Stimulus.Type == Sight && Stimulus.bSuccess:
|
||
LastKnownPlayerLocation = Stimulus.StimulusLocation
|
||
AlertSystem.RaiseAlert(SightAlertValue)
|
||
If AlertSystem.AlertLevel >= AIProfile.CombatThreshold:
|
||
SetTarget(Stimulus.Instigator)
|
||
SetAIState(Combat)
|
||
Else:
|
||
SetAIState(Suspicious)
|
||
└─► If Stimulus.Type == Hearing && Stimulus.bSuccess:
|
||
AlertSystem.RaiseAlert(HearingAlertValue)
|
||
StartInvestigation(Stimulus.StimulusLocation)
|
||
SetAIState(Searching)
|
||
└─► If Stimulus.Type == Damage:
|
||
SetTarget(Stimulus.Instigator)
|
||
AlertSystem.RaiseAlert(DamageAlertValue)
|
||
SetAIState(Combat)
|
||
RequestReinforcements()
|
||
|
||
[OnTakeDamage]
|
||
└─► AlertSystem.RaiseAlert(MaxAlertValue)
|
||
└─► SetTarget(DamageResult.Instigator)
|
||
└─► SetAIState(Combat)
|
||
```
|
||
|
||
### Communications With
|
||
|
||
| Target | Method | Why |
|
||
|--------|--------|-----|
|
||
| [`BP_EnemyBase`](58_BP_EnemyBase.md) | Possessed pawn | Movement, animation, abilities |
|
||
| [`BPC_AIPerceptionSystem`](BPC_AIPerceptionSystem.md) | Get Component | Sensory stimulus processing |
|
||
| [`BB_AgentBoard`](BB_AgentBoard.md) | Get Component | Blackboard updates |
|
||
| [`BPC_AIStateMachine`](61_BPC_AIStateMachine.md) | Get Component | State transitions |
|
||
| [`BPC_AlertSystem`](60_BPC_AlertSystem.md) | Get Component | Threat level queries |
|
||
| [`BPC_HealthSystem`](../02-player/08_BPC_HealthSystem.md) | Get on Pawn | Health events |
|
||
| Nearby AI Controllers | Direct / Event | Reinforcement calls |
|
||
|
||
### Reuse Notes
|
||
- Designed as parent for all enemy types (humanoid, creature, drone)
|
||
- Perception, alerts, and state machine are swappable components
|
||
- Behavior tree is data-driven via AIProfile
|
||
- All decision values (ranges, thresholds, speeds) come from data asset
|
||
- Renamed from `BPC_AIControllerBase` to `AI_BaseAgentController` per Master naming convention.
|
||
- Cross-references updated: `BPC_PerceptionComponent` → `BPC_AIPerceptionSystem`, `BPC_BehaviorTreeManager` → `BB_AgentBoard`, `BPC_HealthComponent` → `BPC_HealthSystem`.
|
||
|
||
---
|
||
|
||
## Manual Implementation Guide
|
||
|
||
### Class Setup
|
||
1. Create Blueprint Class: Parent = `AIController`, Name = `AI_BaseAgentController`
|
||
2. Save to: `Content/Framework/AI/`
|
||
3. In Class Defaults: set `Auto Possess AI` = `Placed in World or Spawned`
|
||
|
||
### Variables (Add to Class Defaults)
|
||
|
||
| Variable | Type | Default | Instance Editable |
|
||
|----------|------|---------|-------------------|
|
||
| `AIProfile` | `DA_AIProfile` | None | ✓ |
|
||
| `PossessedEnemy` | `BP_EnemyBase` (Object Ref) | None | |
|
||
| `BlackboardComp` | `Blackboard Component` (Object Ref) | None | |
|
||
| `BehaviorTreeComp` | `Behavior Tree Component` (Object Ref) | None | |
|
||
| `PerceptionComp` | `BPC_AIPerceptionSystem` (Object Ref) | None | |
|
||
| `StateMachine` | `BPC_AIStateMachine` (Object Ref) | None | |
|
||
| `AlertSystem` | `BPC_AlertSystem` (Object Ref) | None | |
|
||
| `bIsActive` | `Boolean` | `true` | ✓ |
|
||
| `AggressionRange` | `Float` | `1500.0` | ✓ |
|
||
| `SuspicionRange` | `Float` | `3000.0` | ✓ |
|
||
| `CombatRange` | `Float` | `800.0` | ✓ |
|
||
| `HomeLocation` | `Vector` | `(0,0,0)` | |
|
||
| `LastKnownPlayerLocation` | `Vector` | `(0,0,0)` | |
|
||
| `LastKnownPlayerLocation` | `Vector` | `(0,0,0)` | |
|
||
| `bHasLineOfSight` | `Boolean` | `false` | |
|
||
| `LostPlayerTimer` | `Float` | `0.0` | |
|
||
|
||
### Function Implementations
|
||
|
||
#### `Event OnPossess(Pawn: Pawn)`
|
||
|
||
```
|
||
[Event OnPossess]
|
||
Step 1: Call Parent OnPossess
|
||
Step 2: Cast Pawn to BP_EnemyBase → Set PossessedEnemy
|
||
Step 3: Get AIProfile from PossessedEnemy (or a spawner data)
|
||
Step 4: Get Blackboard Component → Set BlackboardComp
|
||
Step 5: Get Behavior Tree Component → Set BehaviorTreeComp
|
||
Step 6: Get Component by Class (BPC_AIPerceptionSystem) → Set PerceptionComp
|
||
└─ If not found on Pawn: Create and attach dynamically
|
||
Step 7: Get Component by Class (BPC_AIStateMachine) → Set StateMachine
|
||
Step 8: Get Component by Class (BPC_AlertSystem) → Set AlertSystem
|
||
Step 9: Set HomeLocation = Pawn.GetActorLocation()
|
||
Step 10: Set Blackboard value "SelfActor" to Self
|
||
Step 11: Set Blackboard value "HomeLocation" to HomeLocation
|
||
Step 12: Set Blackboard value "AIState" to EAIState::Patrol
|
||
Step 13: Run Behavior Tree (AIProfile.BehaviorTree)
|
||
Step 14: PerceptionComp.Initialize(AIProfile.PerceptionConfig)
|
||
Step 15: StateMachine.Initialize(EAIState::Patrol)
|
||
Step 16: AlertSystem.Initialize()
|
||
```
|
||
|
||
**Nodes:** `Cast To BP_EnemyBase`, `Get Blackboard`, `Set Value as Object/Vector/Enum`, `Run Behavior Tree`, `Create Component (if needed)`, `Get Actor Location`
|
||
|
||
#### `Event OnUnPossess(Pawn: Pawn)`
|
||
|
||
```
|
||
[Event OnUnPossess]
|
||
Step 1: Stop Behavior Tree
|
||
Step 2: Clear Blackboard values (TargetActor = None, AIState = Disabled)
|
||
Step 3: PerceptionComp.Deinitialize()
|
||
Step 4: Call Parent OnUnPossess
|
||
```
|
||
|
||
#### `UpdatePerception(Stimulus: AIStimulus)` → `void`
|
||
|
||
*This is called by BPC_AIPerceptionSystem dispatcher when any sense triggers.*
|
||
|
||
```
|
||
[Function: UpdatePerception]
|
||
Step 1: Branch on Stimulus.WasSuccessfullySensed()
|
||
False → Return (ignore failed perception)
|
||
|
||
Step 2: Switch on Stimulus.Type:
|
||
Case Sight:
|
||
Step 2a: Set LastKnownPlayerLocation = Stimulus.StimulusLocation
|
||
Step 2b: AlertSystem.RaiseAlert(SightAlertValue from AIProfile)
|
||
Step 2c: Branch on AlertSystem.AlertLevel >= AIProfile.CombatThreshold:
|
||
True:
|
||
- SetTarget(Stimulus.StimulusLocation → find closest Actor at that location)
|
||
- SetAIState(EAIState::Combat)
|
||
- Set Blackboard "bHasLOS" = true
|
||
False:
|
||
- SetAIState(EAIState::Suspicious)
|
||
- Set Blackboard "StimulusLocation" = Stimulus.StimulusLocation
|
||
- Set Blackboard "bIsInvestigating" = true
|
||
|
||
Case Hearing:
|
||
Step 3a: AlertSystem.RaiseAlert(HearingAlertValue from AIProfile)
|
||
Step 3b: StartInvestigation(Stimulus.StimulusLocation)
|
||
Step 3c: SetAIState(EAIState::Searching)
|
||
Step 3d: Set Blackboard "StimulusLocation" = Stimulus.StimulusLocation
|
||
|
||
Case Damage:
|
||
Step 4a: SetTarget(Stimulus.StimulusLocation → find instigator)
|
||
Step 4b: AlertSystem.RaiseAlert(MaxAlertValue)
|
||
Step 4c: SetAIState(EAIState::Combat)
|
||
Step 4d: Call RequestReinforcements() if team-aware
|
||
|
||
Step 5: Fire OnTargetAcquired(Stimulus.StimulusLocation nearest Actor) if target found
|
||
```
|
||
|
||
**Nodes:** `Switch on EAIPerceptionSense`, `RaiseAlert`, `Set Blackboard Value`, `Branch`, `Find Nearest Actor` or `Get Actor at Location`
|
||
|
||
#### `SetAIState(NewState: EAIState)` → `void`
|
||
|
||
```
|
||
[Function: SetAIState]
|
||
Step 1: Get old state from Blackboard "AIState"
|
||
Step 2: If NewState == OldState → Return
|
||
Step 3: Set Blackboard "AIState" = NewState
|
||
Step 4: Call StateMachine.SetState(NewState)
|
||
Step 5: Fire OnAIStateChanged(OldState, NewState)
|
||
Step 6: If NewState == Combat: Call RequestReinforcements()
|
||
```
|
||
|
||
#### `SetTarget(Target: Actor)` → `void`
|
||
|
||
```
|
||
[Function: SetTarget]
|
||
Step 1: Set Blackboard "TargetActor" = Target
|
||
Step 2: If Target is valid:
|
||
- Set Blackboard "TargetLocation" = Target.GetActorLocation()
|
||
- SetFocus(Target)
|
||
- Fire OnTargetAcquired(Target)
|
||
Else:
|
||
- ClearFocus()
|
||
- Fire OnTargetLost()
|
||
```
|
||
|
||
#### `StartInvestigation(Location: Vector)` → `void`
|
||
|
||
```
|
||
[Function: StartInvestigation]
|
||
Step 1: Set Blackboard "bIsInvestigating" = true
|
||
Step 2: Set Blackboard "TargetLocation" = Location
|
||
Step 3: Call AI MoveTo(Location)
|
||
Step 4: On Move Completed:
|
||
- If target not found at location:
|
||
- Set Blackboard "bIsInvestigating" = false
|
||
- ReturnToPatrol()
|
||
```
|
||
|
||
#### `RequestReinforcements()` → `void`
|
||
|
||
```
|
||
[Function: RequestReinforcements]
|
||
Step 1: Get all AI_BaseAgentController in radius (ReinforcementRange from AIProfile)
|
||
Step 2: ForEach nearby AI:
|
||
- If AI.StateMachine.CurrentState == Patrol OR Suspicious:
|
||
- Call AI.SetTarget(Self.GetBlackboard("TargetActor"))
|
||
- Call AI.SetAIState(Alerted)
|
||
Step 3: Fire OnReinforcementRequested(Self.GetActorLocation())
|
||
```
|
||
|
||
**Nodes:** `Get All Actors of Class (AI_BaseAgentController)`, `ForEachLoop`, `Get Distance To`, `Branch`, `Call SetTarget/SetAIState on other AI`
|
||
|
||
#### `LostSightOfTarget()` → `void`
|
||
|
||
```
|
||
[Function: LostSightOfTarget]
|
||
Step 1: Set Blackboard "bHasLOS" = false
|
||
Step 2: Start LostPlayerTimer (timer loops 0.1s)
|
||
└─ Each tick: LostPlayerTimer += 0.1
|
||
Step 3: Branch on LostPlayerTimer >= AIProfile.LostTargetTimeout:
|
||
True:
|
||
- ClearTarget()
|
||
- SetAIState(EAIState::Searching)
|
||
- StartInvestigation(LastKnownPlayerLocation)
|
||
- Clear LostPlayerTimer
|
||
False: continue waiting
|
||
```
|
||
|
||
#### `CanSeeTarget()` → `Boolean`
|
||
|
||
```
|
||
[Function: CanSeeTarget] (Pure)
|
||
Step 1: TargetActor = Get Blackboard "TargetActor"
|
||
Step 2: If TargetActor NOT valid → Return false
|
||
Step 3: Line Trace by Channel from Self location to TargetActor location
|
||
- Trace channel: Visibility
|
||
- Ignore Self
|
||
Step 4: Return (Hit Actor == TargetActor) — true if nothing blocks line of sight
|
||
```
|
||
|
||
### Blueprint Build Checklist
|
||
|
||
- [ ] Create AI_BaseAgentController (Parent: AIController)
|
||
- [ ] Add all variables from the table above
|
||
- [ ] Create Blackboard asset: BB_AgentBoard with all key names
|
||
- [ ] Configure Behavior Tree asset (or use placeholder)
|
||
- [ ] Implement OnPossess: cache components, init perception/state/alert, run BT
|
||
- [ ] Implement UpdatePerception: route Sight/Hearing/Damage to correct states
|
||
- [ ] Implement SetAIState with blackboard update and dispatcher
|
||
- [ ] Implement SetTarget/ClearTarget with blackboard sync
|
||
- [ ] Implement StartInvestigation with AI MoveTo
|
||
- [ ] Implement RequestReinforcements (nearby AI coordination)
|
||
- [ ] Implement LostSightOfTarget with timeout → search
|
||
- [ ] Implement CanSeeTarget with line trace
|
||
- [ ] Create BP_EnemyBase child classes that use this controller |