Step-by-Step Enemy Creation

Documentation Unreal Engine AI Tutorial

Comprehensive guide to creating a complete enemy from scratch with weapons, animations, and advanced features.


This guide walks through creating a complete enemy from scratch, including weapons, animations, and full AI behavior.

Prerequisites

Before starting, ensure you have:
  • Character skeletal mesh with attack animations
  • Attack animation montages with hit frames identified
  • Basic understanding of Gameplay Ability System
  • Unreal Engine 5.6+ installed

Step 1: Character Setup

Create Blueprint: BP_DetailedEnemy (inherits AEnemyCharacterBase)
In Components Panel:
  1. Select SkeletalMesh component and set your character mesh
  2. Select CapsuleComponent and adjust radius/height to fit mesh
  3. Select CharacterMovement component and adjust if needed
What the base class provides automatically:
  • USECMeleeTraceComponent for hit detection
  • UAbilitySystemComponent (configured)
  • IAbilitySystemInterface (implemented)
  • USECActionSetComponent for action set resolution and replicated action state
  • USECCombatRoleComponent for replicated combat role
Set AIConfig: In the Details Panel, set AIConfig to DA_AIConfig_EnemyDefault (included with the plugin) or your own UEnemyAIConfig data asset.
The controller's SECCombatControllerComponent checks the pawn for an AIConfig first. If none is set on the pawn, the component uses its own DefaultAIConfig fallback. If neither is set, there will be no AI behavior.
Not inheriting from EnemyCharacterBase? Add SECMeleeTraceComponent, SECActionSetComponent, and SECCombatRoleComponent manually. Implement IAbilitySystemInterface and set up your own AbilitySystemComponent. The system only requires these components to be present on the pawn.

Step 2: AI Controller Setup

Create Blueprint: BP_DetailedEnemyController (inherits AEnemyControllerBase)
What the base class provides:
// These components are created as default subobjects:
USECCombatControllerComponent*  // Combat system integration (AIConfig, roles, sync)
UMovementEvaluatorComponent*    // Tactical movement direction selection
UActionEvaluationComponent*     // Action scoring and execution
UThreatDetectionComponent*      // Player attention tracking
UBotStateTreeAIComponent*       // StateTree AI runner
UBehaviorTreeComponent*         // Helper BT for action sequences (not the BrainComponent)
Additional features: smooth focus rotation with LockRotation/UnlockRotation, team ID via ISECTeamInterface, and K2 Blueprint events for role changes and target loss.

Option B: Use Any AAIController + Components

If you have an existing AI controller, add SECCombatControllerComponent in the Components panel. Then add whichever other SEC components you need (MovementEvaluatorComponent, ActionEvaluationComponent, etc.). Everything connects automatically on possession.
Threat-to-movement response is auto-wired if both ThreatDetectionComponent and MovementEvaluatorComponent are present. Configure bSwapStrafeOnHighThreat and bAdjustDistanceByThreat on the MovementEvaluatorComponent (or through a MovementBehaviorProfile).
Customization hooks: Subclass SECCombatControllerComponent in Blueprint and override SyncStateForCombatRole (custom role-change behavior) or HandleCombatTargetLost (custom target-loss fallback). Subclass ActionEvaluationComponent and override CanExecuteAction for custom action gating.
Movement settings are on the MovementEvaluatorComponent. The defaults from the showcase controller work well for smooth, realistic movement. Enable bDebugLog to see movement decisions in the output log.

Step 3: Create an ActionSet

Create Data Asset: DA_DetailedEnemyActions (type: ActionSet)
Add actions to the Actions array. Each entry is an FActionSpec.

Action 1: Light Attack (Close Range)

PropertyValueNotes
ActionIdLightAttackUnique identifier for chaining and cooldowns
ExecutionModeGameplayAbilitySimple ability execution
AbilityClassGA_LightAttackAbilityTag and AbilityEndTag are auto-generated from the class
DistanceEval
↳ MinValue0Valid from 0cm
↳ OptimalMin100Score = 1.0 starts
↳ OptimalMax250Score = 1.0 ends
↳ MaxValue400Score = 0 beyond this
AngleEval
↳ OptimalMax30Up to 30 degrees is ideal
↳ MaxValue90Not used beyond 90 degrees
Cooldown
↳ Duration2.02 second cooldown
↳ InitialCooldown1.0Cannot use during first second after spawn
SelectionWeight1.0Base selection weight

Action 2: Heavy Attack (Medium Range)

PropertyValueNotes
ActionIdHeavyAttack
ExecutionModeGameplayAbility
AbilityClassGA_HeavyAttack
DistanceEval: OptimalMin150Slightly farther than light
DistanceEval: OptimalMax300
Cooldown: Duration4.0Longer cooldown
SelectionWeight0.8Lower base weight
RiskPenalty1.5Divides score, making it less frequent
To make this combo from a light attack, set PreferredNextActionId to HeavyAttack on the LightAttack action, and set ChainBonusMultiplier to 1.5 for a 50% score boost when chaining.

Action 3: Defensive Retreat (When Too Close)

PropertyValueNotes
ActionIdQuickRetreat
ExecutionModeBehaviorTreeSequenceUses a BT for movement logic
BehaviorTreeSequence[BT_QuickBackstep]Array of BTs to run in order
DistanceEval: OptimalMin0Best when very close
DistanceEval: OptimalMax100
Cooldown: Duration3.0
SelectionWeight1.5Higher priority when in range
TagScoreMultipliers
State.PlayerAttacking2.0Doubles score when player is attacking
TagScoreMultipliers is a map of FGameplayTag to float. If the target or AI has a matching tag, the score is multiplied by that value. Use tags like State.Stunned (2.0), State.Blocking (0.3), Self.Enraged (1.5) to create context-aware behavior.

Step 4: Create Gameplay Abilities

For each action using GameplayAbility execution mode, create an ability Blueprint.
Recommended: Inherit from GameplayAbilityBase (included in the plugin). This base class automatically sends the AbilityEndTag event when the ability ends, even if interrupted. If you do not use this base class, you must send the end tag manually or the AI will get stuck.
Example: GA_LightAttack (inheriting from GameplayAbilityBase)
Event ActivateAbility
  ↓
Play Montage and Wait
  • Montage: AM_LightAttack
  • Rate: 1.0
  ↓ On Completed / On Cancelled / On Interrupted
End Ability
If not inheriting from GameplayAbilityBase: You must call SendGameplayEventToActor with the AbilityEndTag in every exit path (completed, cancelled, interrupted). The ActionEvaluationComponent waits for this event to know the action finished. The built-in GA_SEC_Attack is a reference implementation that handles this correctly.

Step 5: Configure Animation Montages

Create Montage: AM_LightAttack from your attack animation
Add Melee Trace Notify State:
  1. Right-click the timeline at the attack's active frames
  2. Add Notify State ➜ SECMeleeTraceWindow
  3. Set the duration to cover the weapon swing (e.g., frames 10-25)
  4. Optionally add a MotionWarping notify state for chase behavior during specific frames
Configure the Notify State:
In the Details Panel of the SECMeleeTraceWindow notify:
  • Socket IDs: ["Blade"] - This must match the trace socket ID registered on the weapon (see Step 6), not a skeleton socket name
  • DamageConfig: DA_SwordDamage - Assign the damage configuration data asset here
Timing Example:
Frame:     0    10    20    30    40    50
Animation: [━━━━][━━━━][━━━━][━━━━][━━━━]
           Windup Strike  Follow Recovery
Trace:          [═════════]

Step 6: Create Weapon

Create Blueprint: BP_Sword (inherits ASECWeaponBase)
Class Defaults:
PropertyValueNotes
AttachSockethand_rSocket name on the character skeleton (default)
AttachOffsetFTransform::IdentityRelative transform applied after attachment
AnimLayerToUse(optional)Animation layer class to apply when equipped
TraceSockets Array:
Add an element:
PropertyValueNotes
IDBladeMust match the Socket IDs in the montage notify
ShapeCapsuleTwoPointTrace shape (Sphere, Capsule, CapsuleTwoPoint)
SocketOrBoneNameblade_startSocket on weapon mesh (start point)
EndSocketOrBoneNameblade_endSocket on weapon mesh (end point)
Radius15.0Trace radius
Weapon Mesh Setup:
  1. The base class does not add a mesh component by default. Add a StaticMeshComponent or SkeletalMeshComponent and set your mesh.
  2. Add sockets to the weapon mesh: blade_start at the blade base, blade_end at the blade tip
  3. Position sockets along the cutting edge
For different weapon types, select the trace shape that fits best. A hammer could use Sphere, a spear could use CapsuleTwoPoint with a longer radius. The FSECTraceSocket supports multiple shapes for different scenarios.
What Happens Automatically:
  • On equip: Registers trace sockets with the character's SECMeleeTraceComponent
  • During montage notify: Traces activate between sockets
  • On hit: Applies damage via the SECDamageConfig assigned on the notify state
The system calls Unreal's ApplyDamage on hit. If you need a custom damage pipeline, you can listen to the delegates on SECMeleeTraceComponent and handle damage your own way.

Step 7: Create Damage Configuration

Create Data Asset: DA_SwordDamage (type: SECDamageConfig)
PropertyDefaultNotes
Damage10.0Base damage amount
DamageTypeClassUDamageTypeDamage type passed to ApplyDamage
AttackTag(empty)Optional gameplay tag for reactions/resistances
bCanBeBlockedtrueWhether this attack can be blocked
bCanBeParriedtrueWhether this attack can be parried
StaggerStrength10.0Poise damage (how much it breaks stance)
KnockbackStrength0.0Knockback force on hit
SECDamageConfig is Blueprintable. If you need additional properties (elemental types, status effects), create a Blueprint child class and add your custom fields.

Step 8: Build StateTree Logic

For most cases, use the included StateTree_SEC_Core instead of building from scratch. It handles the standard combat loop out of the box. The breakdown below is for learning or for situations where you need a fully custom tree.
Create StateTree: ST_DetailedEnemy
Core StateTree structure:
StateTree: (Core)

├─ Root State
│  │
│  ├─ Combat State
│  │  • Condition: Target is valid AND role is not SEC.Role.None
│  │  │
│  │  ├─ Role State
│  │  │  • Condition: SEC.Role.* matches current role
│  │  │  └─ Linked Subtree: → StateTree_SEC_MoveAndAction
│  │
│  └─ Idle State
│     • Task: Delay 1.0

StateTree: StateTree_SEC_MoveAndAction

├─ Root State
│  • Task: Sync Action Set from Pawn
│  │
│  └─ Role State
│     • Tasks: PollTargetActor, Build Decision Context, Poll Action
│     │
│     ├─ Move State
│     │  • Task: AI Movement (Distance: 600)
│     │  └─ Transition → Action State
│     │
│     ├─ Action State
│     │  • Task: Do Action
│     │  ├─ Transition → Recovery State (Success)
│     │  └─ Transition → Role State (Failure)
│     │
│     └─ Recovery State
│        • Task: Delay Parameters.RecoveryDuration
│        └─ Transition → Role State

Step 9: Test Your Enemy

Place in Level:
  1. Drag BP_DetailedEnemy into the level
  2. In Details Panel ➜ Pawn ➜ AI Controller Class ➜ set to BP_DetailedEnemyController
Debug Configuration:
Enable per-component logging:
ActionEvaluationComponent → bDebugLog: true
MovementEvaluatorComponent → bDebugLog: true
Expected Output Log Messages:
LogEvaluation: Evaluating 3 actions for BP_DetailedEnemy_1...
LogEvaluation: [LightAttack] Dist:180 Angle:15 Score:0.95 SELECTED
LogEvaluation: [HeavyAttack] Dist:180 Angle:15 Score:0.60 (cooldown)
LogEvaluation: [QuickRetreat] Dist:180 Angle:15 Score:0.10 (too far)
Expected Behavior:
  • Approaches to ideal distance range
  • Strafes around player
  • Executes light attack when in optimal range
  • Occasionally uses heavy attack with combo chaining
  • Retreats if player gets too close or is attacking

Common Issues

ProblemCauseSolution
AI does not attackAbility not activatingCheck AbilityClass is set on the action, verify ASC grants the ability
AI repeats same actionOnly one action scores wellAdd more actions with different distance/angle ranges
AI does not moveMovement not drivenCheck STTask_AIMovement is present and ticking in the StateTree
Weapon does not hitSocket mismatchVerify the notify state's Socket IDs match the weapon's TraceSockets ID
AI gets stuck after attackEnd tag not sentUse GameplayAbilityBase or manually send the AbilityEndTag event