Debugging & Troubleshooting
Documentation Unreal Engine AI FAQ
Debug flags, console variables, common failures, and FAQ.
Flip Debug flags on the combat components or runSEC.Debug.*console variables when an enemy misbehaves. Match log output to the sections below.
Component Debug Flags
Toggle these on the AI controller, which is where the evaluation components sit.
Details
Action Evaluation Component (ActionEvaluationComponent)
Debug
Debug Log Decisions
Debug Log Execution
Component flags OR matching SEC.Debug.* console variables enable the same logs.
Details
Movement Evaluator Component (MovementEvaluatorComponent)
Debug | Draw
Debug Draw Scoring
Debug Draw Avoidance
Debug Draw Nav
Debug | Log
Debug Log Movement
Debug Log Tick
Debug Log Scoring
Debug Log Avoidance
Debug Log Strafe Swap
Debug Log Strafe State
Component flags OR matching SEC.Debug.Movement.* console variables enable the same output.
Reactions:
bDebugLogReactions on UReactionEvaluationComponent, or SEC.Debug.LogReactions 1.Melee traces:
bDrawDebug on USECMeleeTraceComponent, or SEC.Debug.Melee.DrawTracing 1.With
bDebugLogDecisions or SEC.Debug.LogActionDecisions 1, the Output Log prints lines like:[EvalComp] LightAttack: Ctx=1.00 Nov=1.00 Chain=1.00 Risk=1.00 Runtime=1.00 Custom=0.95 -> 0.95
[EvalComp] HeavyAttack BLOCKED: On cooldown (1.2s remaining)
[EvalComp] Committed to: LightAttack (score 0.95)
An action stopped by a hard gate never reaches a score line; it prints
BLOCKED with the reason instead. Custom folds every scorer on the action (Distance, Angle, Health, Speed, plus any you add). Per-scorer values sit in the score breakdown under each scorer's display name.Component flags and their matching CVars stack: either one turns the output on.
Console Commands
All commands are cheat CVars. Pass
0 or 1 unless noted.| Console variable | Output |
|---|---|
SEC.Debug.LogActionDecisions | Action scoring and selection |
SEC.Debug.LogActionExecution | Start, end, cooldowns |
SEC.Debug.LogReactions | Reaction evaluation and execution |
SEC.Debug.LogRoleAssignments | Role assignment (2 = verbose) |
SEC.Debug.Threat.Log | Threat events |
SEC.Debug.Threat.Draw | Threat cone, progress arc, AI color grading |
SEC.Debug.Movement.DrawScoring | Direction sample lines (red low, green high) |
SEC.Debug.Movement.DrawAvoidance | Avoidance radius and blocked pawns |
SEC.Debug.Movement.DrawNav | Nav sample validity (blue blocked, white walkable) |
SEC.Debug.Movement.LogMovement | Layer changes, pathfinding, stuck, detour |
SEC.Debug.Movement.LogTick | Per-tick state dump (high frequency) |
SEC.Debug.Movement.LogScoring | Direction scoring |
SEC.Debug.Movement.LogAvoidance | Avoidance detection |
SEC.Debug.Movement.LogStrafeSwap | Strafe swap decisions |
SEC.Debug.Movement.LogStrafeState | Strafe state and timers |
SEC.Debug.Melee.DrawTracing | Weapon sweep shapes |
Common Issues
AI doesn't attack
Check first:
- The ASC on the pawn holds the ability with a tag that matches the
ActionSetentry. - The action is off cooldown and
FinalScore > 0after scorers run. ActiveActionSetonActionEvaluationComponentpoints at the set you expect.
Ability not granted: The action system grants the execution method's Ability Class to the ability system itself, once a valid one exists. Two log lines explain a failure:
Cannot grant ability for <action> - ASC is invalid! means the ability system was not ready when actions initialised, and <action> doesn't have any ability or behavior tree set means the execution method carries no class. BTTask_ActivateAbility exposes bGrantAbilityIfMissing for a standalone Behavior Tree setup that bypasses the action system.Tag mismatch:
TryActivateAbilitiesByTag matches tags on the ability CDO's AbilityTags. If the ability has no tags there, switch the execution method to ByEvent or add the tag in class defaults.ByEvent path: The ability class needs a Trigger entry with Trigger Source = Gameplay Event for the event tag.
No ASC found: Custom pawns must implement
IAbilitySystemInterface and return a valid ASC. The no-C++ path is reparenting to EnemyCharacterBase. See Getting Started.Range: Add a Distance Scorer to the action and tune its
Range. An action with no Distance Scorer ignores distance.Debug: Enable
bDebugLogDecisions and read why each action failed or lost selection.Enemy pauses between attacks
Recovery time blocks offensive action selection while movement and reactions keep running. Cooldown is separate.
Tune on
UEnemyAIConfig, Recovery section:ActionRecoveryTime: gap between attacks. All zeros disable recovery.InterruptRecoveryTime: lockout after parry or stagger. Keep it belowActionRecoveryTime.- Per-action
RecoveryTimewhenbOverrideRecoveryTimeis on replaces the global for that action only.
Confirm:
SEC.Debug.LogActionDecisions 1 prints Recovering (X.Xs remaining). IsActionRecovering() exposes the same timer to a debug widget.A behavior tree action starts nothing
Cause: The blackboard has no key for the action's payload, so the tree receives nothing to act on. A blackboard write to a missing key is dropped by the engine, and the log names the key once per blackboard:
could not hand its payload to the behavior tree.Fix: Add these keys to the blackboard asset:
| Key | Type | Base Class |
|---|---|---|
SEC_Payload | Object | SECBehaviorTreePayload |
SEC_ActionId | Name | |
SEC_TargetActor | Object | |
SEC_SelfActor | Object | |
SEC_Distance | Float |
Then point the Payload Key on the Activate Blackboard Ability node at
SEC_Payload.AI stuck after attacking
Cause: The ability the action started never ends, so the action keeps waiting on it.
Fix:
- Give the ability a path that reaches End Ability on completion, on cancel, and on interrupt. An ability that plays a montage through Play Montage and Wait ends when the montage does.
- Set Ability Timeout on the action to bound the wait. A 30 second safety limit catches it either way, and logs the action and ability that hit it.
- For an ability that is meant to keep running, use the Gameplay Ability (Fire And Forget) method so the action finishes immediately without waiting.
A revived or pooled enemy never acts again
Cause: Death blocks action evaluation on that controller, and only a revive releases it. An enemy brought back, or a controller reused from a pool, is still holding the block.
Fix: Call
HandleRevive() on the SEC Combat Controller component when the enemy comes back. It releases the block, restarts the brain, and turns threat detection, perception and role registration back on. Re-equip the weapon yourself; death dropped it.Weapon doesn't deal damage
Read the Output Log first. The trace component names most of these itself: a socket a window asked for that nothing registered, a window opening while another was still open, a socket sweeping from a mesh that is not refreshing its bones, an Object Types filter with an empty list, and a socket ID another component already holds.
Check:
- Socket IDs on the anim notify match
TraceSocketson the weapon exactly. - The Trace Filter reaches the target: in Channel mode the channel the target blocks, in Object Types mode the type it belongs to (use
SEC.Debug.Melee.DrawTracing 1). - The pawn has
USECMeleeTraceComponent(EnemyCharacterBaseadds it by default). Default Damage Configon the trace component orDamage Configon the melee notify state supplies aUSECDamageConfig. Damage does not come from the weapon actor class alone.
See Melee Trace.
AI doesn't move
Check:
- A NavMeshBoundsVolume covers the play area. Press P in the viewport to visualize it.
- In a StateTree graph, AI Movement stays in a running state during combat so
STTask_AIMovementcan tick. See StateTree Integration. HybridSwitchDistanceonMovementEvaluatorComponent(default 800 cm) sets where tactical sampling hands off to strategic pathfinding. Lower it if the enemy never switches to pathfinding at range; raise it if it pathfinds too close.
Enable
bDebugLogMovement or SEC.Debug.Movement.LogMovement 1 for layer and pathfinding events.Enemy jogs instead of running while closing distance
Cause: sideways movement costs speed, and direction scoring angles the approach a few degrees while the AI holds a strafe side or steps around another enemy.
Fix: raise
StrafeFreeAngle on MovementEvaluatorComponent (default 15 degrees), the band around straight ahead that costs no speed. StrafeSpeedPenalty (0.75) softens the cost everywhere including real circling, and 0 turns it off. Also check the run window in your locomotion graph, since a 30 degree approach keeps 65% of its speed by design.AI walks off ledges or into hazards
Check:
- NavMesh ends before the visual drop (press P).
bEnableNavAwareSamplingis on andNavScoreWeightis above 0.- A hazard painted only as high nav cost still reads as walkable at close range. Add the NavArea subclass to Hazard Area Avoidance on the movement component with a strength around 0.75; the value is the avoidance weight, where 0 ignores the area and 1 scores it like a wall.
Debug:
SEC.Debug.Movement.DrawNav 1 marks blocked directions with blue spheres.Tune
NavProbeDistance (default 120): lower in tight spaces, higher for fast movers. See Movement System.AI grinds against a wall
The target sits behind cover. Straight-line distance stays short while the nav path is long, so the AI strafes into geometry.
Check on
MovementEvaluatorComponent, Hybrid Movement > Detour:bEnableDetourEscalationis on.- NavMesh routes around the obstacle.
bDetourEscalateOnStallcatches tight corners; raiseDetourStallSpeedif a slow grind does not register.- Lower
DetourEnterRatio(try 1.4) orDetourMinExcesswhen a longer detour still reads as minor.
Debug:
SEC.Debug.Movement.LogMovement 1 logs detour recheck lines (ENGAGE, HOLD, release).See Detour tuning knobs.
Waiter or Flanker freezes after the player jumps a gap
The player sits close in a straight line but the walkable route still wraps around the pit. Waiter and Flanker can already be inside their desired-distance band, so tactical steering idles at the rim while sight stays clear across the gap.
Check on
MovementEvaluatorComponent, Hybrid Movement > Detour:bEnableDetourEscalationis on.- Both sides of the gap sit on connected navmesh. A route that stops at the rim means there is no walkable way across, and the AI correctly stays tactical rather than walking into a dead end.
- Leave
bDetourUseLineOfSightPreGateon. It reads the navmesh along the straight line, so a gap engages the detour with sight clear. - Lower
DetourReleaseRatioonly if the AI gives up the route too early on a short way around.
Debug:
SEC.Debug.Movement.LogMovement 1 prints Detour eval: active, HOLD while the route still detours, and Detour eval: skip (no reachable route) when the far side is not connected.See Detour tuning knobs.
FAQ
Can I use this with my existing character?
Add
SECCombatControllerComponent to your AI controller and the pawn components from Getting Started. Assign an EnemyAIConfig and ActionSet. Leave Default State Tree empty for the native combat loop, or assign a StateTree asset. You do not need to inherit EnemyControllerBase or EnemyCharacterBase.Does this work with multiplayer?
Yes. AI logic runs on the server. Health, action execution, combat roles, and the active
ActionSet replicate to clients. See Multiplayer.Can I use this without GAS?
Melee trace works without GAS. Action execution through abilities needs GAS for blocking tags, cooldown integration, and
GameplayAbilityBase end-tag wiring. Behavior Tree-only execution methods skip ability activation when you wire them that way.What engine versions are supported?
UE 5.6, 5.7, and 5.8. Plugin version 3.0.0.
How do I handle death (ragdoll, weapon drop, dissolve)?
Call
HandleDeath() on SECCombatControllerComponent. It shuts down SEC systems in order and fires OnDeath.Weapon drop:
HandleDeath unequips with bSimulatePhysics = true. Override K2_OnUnequipped on the weapon Blueprint for mesh physics and impulse. Set bDropWeaponOnDeath to false on the combat controller to handle the drop yourself (for example from a death montage notify).Ragdoll: Enable it from
OnDeath or K2_OnDeath. Combat systems are already off.Dissolve / destroy: Use
SetLifeSpan or a timer in K2_OnDeath before destroying the actor.Is source code included?
Yes. Full C++ source ships with the plugin.
Support
Purchase and updates: Fab Marketplace
Support and feature requests: Discord, Fab Marketplace, or email (contact details on the product page).