Step-by-Step Enemy Creation
Comprehensive guide to creating a complete enemy from scratch with weapons, animations, and advanced features.
This section provides comprehensive instructions for creating a complete enemy from scratch, including weapons, animations, and advanced features.
Prerequisites
Before starting, ensure you have:
- Character skeletal mesh with animations
- Attack animation montages with hit frames identified
- Basic understanding of Gameplay Ability System
- Unreal Engine 5.7 installed
Step 1: Character Setup
Create Blueprint: BP_DetailedEnemy (inherits AEnemyCharacterBase)
In Components Panel:
-
Select SkeletalMesh component
- Set your character mesh
- Configure materials
-
Select CapsuleComponent
- Adjust radius to fit mesh
- Set height appropriately
-
Select CharacterMovement component
Adjust movement component settings if you want.
What You Get Automatically:
-
USECMeleeTraceComponent- Already added by base class -
UAbilitySystemComponent- Already configured -
IAbilitySystemInterface- Already implemented -
AIConfig-> Set it to your AI Config or theDA_SEC_Enemy_AIConfig_Default
AIConfig will be acquired from the pawn by the controller if it's set here. If it is not set in the pawn, AIController will try to use it's own. If that is also not set, there will be no AI behavior.
Step 2: AI Controller Setup
Create Blueprint: BP_DetailedEnemyController (inherits AEnemyControllerBase)
What the base class provides:
// These components are automatically added:
UMovementEvaluatorComponent* // Tactical movement
UThreatDetectionComponent* // Player attention tracking
UActionEvaluationComponent* // Action scoring & execution
UBehaviorTreeComponent* // For BT sequence executionConfigure Movement:
Open BP_DetailedEnemyController → Details Panel → Movement Evaluator:
Movement Evaluator:
There are a lot of movement related settings.
Default values on `BP_SEC_EnemyController` work well for a smooth and realistic looking enemy.
You can configure these settings further.
Debug:
bDebugLog: false (enable to see movement decisions)
Configure Action Evaluation:
Details Panel → Action Evaluation:
CurrentActionSet: DA_DetailedEnemyActions (create next)
bDebugLog: true (enable to see action scoring)
ActionSet is updated by the StateTree depending on the current role. This is defined inside the AIConfig.
Step 3: Create Comprehensive ActionSet
Create Data Asset: DA_DetailedEnemyActions (type: ActionSet)
Add Multiple Actions for Variety:
Action 1: Light Attack (Close Range)
| Property | Value | Notes |
|---|---|---|
| Id | LightAttack | Unique identifier |
| DisplayName | Light Attack | Editor display |
| ExecutionMode | GameplayAbility | Simple ability execution |
| AbilityTag | SEC.Action.LightAttack | Triggers GA_LightAttack |
| AbilityEndTag | SEC.Action.End | Completion signal |
| Distance | ||
| ↳ MinValue | 0 | Valid from 0cm |
| ↳ OptimalMin | 100 | Score = 1.0 starts |
| ↳ OptimalMax | 250 | Score = 1.0 ends |
| ↳ MaxValue | 400 | Invalid beyond |
| Angle | ||
| ↳ MinValue | 0 | Must face target |
| ↳ OptimalMin | 0 | Perfect facing |
| ↳ OptimalMax | 30 | Up to 30° good |
| ↳ MaxValue | 90 | Don't use >90° |
| Cooldown | ||
| ↳ Duration | 2.0 | 2 second cooldown |
| ↳ WarmupCooldown | 1.0 | Can't use first 1s |
| BaseWeight | 1.0 | Selection priority |
| bRequireLOS | true | Need line of sight |
Action 2: Heavy Attack (Medium Range)
| Property | Value | Notes |
|---|---|---|
| Id | HeavyAttack | |
| ExecutionMode | GameplayAbility | |
| AbilityTag | SEC.Action.HeavyAttack | |
| AbilityEndTag | SEC.Action.End | |
| Distance: OptimalMin | 150 | Slightly farther |
| Distance: OptimalMax | 300 | |
| Cooldown: Duration | 4.0 | Longer cooldown |
| BaseWeight | 0.8 | Lower priority |
| Chain From | LightAttack | Can combo after light |
| Chain Bonus | 0.5 | +50% score if chaining |
Action 3: Defensive Retreat (When Too Close)
| Property | Value | Notes |
|---|---|---|
| Id | QuickRetreat | |
| ExecutionMode | BehaviorTreeSequence | Uses BT for movement |
| BehaviorTrees | [BT_QuickBackstep] | Array of BTs to run |
| Distance: OptimalMin | 0 | Use when very close |
| Distance: OptimalMax | 100 | |
| Cooldown: Duration | 3.0 | |
| BaseWeight | 1.5 | Higher priority |
| Context Modifiers: | ||
↳ Tag: Player.Attacking | Multiplier: 2.0 | Much higher score if player attacking |
Step 4: Create Gameplay Abilities
For each action using GameplayAbility execution mode, create an ability Blueprint inheriting from GameplayAbilityBase.
Example: GA_LightAttack
Class Defaults:
- Ability Tags:
SEC.Action.LightAttack
Event Graph Implementation:
Event ActivateAbility
↓
[Branch: Check if montage valid]
↓ True
Play Montage and Wait
• Montage: AM_LightAttack
• Rate: 1.0
↓ On Completed
Send Gameplay Event to Actor
• Target: Get Avatar Actor from Actor Info
• Event Tag: SEC.Action.End
• Payload: (optional ActionInfo)
↓
End Ability
• Cancel: false
↓ On Cancelled/Interrupted
Send Gameplay Event to Actor (SEC.Action.End)
↓
End Ability
Important: All of this is covered inside the GA_SEC_Attack, if you choose to not derive from GameplayAbilityBase, always send the ability end tag event, even if interrupted. Otherwise, the AI gets stuck. Action evaluator needs to know when ability is done. This is automatically handled if you are using GameplayAbilityBase as your parent class for abilities.
Step 5: Configure Animation Montages
Create Montage: AM_LightAttack from your attack animation
Add Melee Trace Notify State:
- Right-click timeline at attack's active frames
- Add Notify State →
SECMeleeTraceWindow - Duration: Cover the weapon swing (e.g., frames 10-25)
- Add MotionWarping notify state if you want chase behavior during the attacks in certain frames.

Configure Notify State:
Details Panel:
Socket IDs: ["Blade"] // Must match weapon trace socket,
not the mesh socket, the trace socket that is registered on the SECMeleeTrace component
Timing Example:
Frame: 0 10 20 30 40 50
Animation: [━━━━][━━━━][━━━━][━━━━][━━━━]
Windup Strike Follow Recovery
Trace: [═════════]
End Event: ▲
Step 6: Create Weapon
Create Blueprint: BP_Sword (inherits ASECWeaponBase)
Class Defaults:
Attachment:
AttachSocket: "RightHandSocket" // Socket on character skeleton
AttackOffset: Relative offset that will be applied after attachment
Trace Sockets Array:
Add element [0]:
ID: "Blade"
Shape: CapsuleTwoPoint
SocketOrBoneName: "blade_start" // Socket on weapon mesh
EndSocketOrBoneName: "blade_end" // Socket on weapon mesh
Radius: 15.0
TraceChannel: ECC_Pawn
Damage Configuration:
DamageConfig: DA_SwordDamage // Create data asset from `SECDamageConfig`
Weapon Mesh Setup:
- Components → WeaponMesh → Set your sword static/skeletal mesh
- Add sockets to weapon mesh:
blade_startat blade baseblade_endat blade tip
- Position sockets along the cutting edge
For different types of weapons, there are multiple selections for how should the trace work, for example, a hammer can use Sphere instead of CapsuleTwoPoint. You can select what works the best for your case.
What Happens Automatically:
- On equip → Registers trace sockets with character's
MeleeTraceComponent - During montage notify → Traces activate between sockets
- On hit → Applies damage via DamageConfig
The Apply Damage function is called on the actor that has been hit, this function is from unreal. If you want to implement your own way of communicating the damage, you can just ignore this and implement it on top. Both SECMeleeTrace component has functions and delegates you can listen to easily.
Step 7: Create Damage Configuration
Create Data Asset: DA_SwordDamage (type: SECDamageConfig)
Damage: 25.0
DamageType: UDamageType (or custom class)
SECDamageConfig comes with common use-case variables, like "CanBeBlocked", "CanBeParried".
If you need more, you can create a blueprint inheriting SECDamageConfig and extend the data.
Step 8: Build StateTree Logic
For this step, i highly recommend using "StateTree_SEC_Core" instead. For majority of the cases it will work as expected. Otherwise you can learn from it.
Create StateTree: ST_DetailedEnemy
Root State Configuration:

StateTree: (Core)
├─ Root State
│ │
│ ├─ Combat State
│ │ • Condition: (Is Object Valid) AND (Not SEC.Role.None contains exactly PollCombatRole.OutCombatRole)
│ │ │
│ │ ├─ Role State
│ │ │ • Condition: SEC.Role.* contains exactly PollCombatRole.OutCombatRole
│ │ │ └─ Linked Subtree: *_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
│ │ • Condition: ASC Has Tag
│ │ • 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:
- Drag
BP_DetailedEnemyinto level - Details Panel → Pawn → AI Controller Class →
BP_DetailedEnemyController
Debug Configuration:
Enable logging in controller:
ActionEvaluation → bDebugLog: true
MovementEvaluator → bDebugLog: true
Play and Observe:
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
- Retreats if player gets too close
Common Issues
| Problem | Cause | Solution |
|---|---|---|
| AI doesn't attack | Ability not activating | Check AbilityTag matches, verify ASC grants ability |
| AI repeats same action | Only one action valid | Add more actions with different ranges |
| AI doesn't move | Movement not enabled | Check STTask_AIMovement is ticking |
| Weapon doesn't hit | Socket mismatch | Verify notify Socket IDs match weapon TraceSockets IDs |
