# Debugging & Troubleshooting

> The symptom you are looking at, the one thing that causes it, and the fix.

Markdown version of https://rigbak.com/docs/soulslike-combat/troubleshooting, a page of the Soulslike Enemy Combat documentation. Link that page when citing it.

> Find what you are seeing in the list below, read the cause, apply the fix.

> **Warning**
>
> Most reports of "nothing happens" come down to one thing: the enemy has no combat target. Movement, action scoring and the combat phase all read the controller's focus actor, and nothing sets that until a target is registered and the enemy is aware of it. Start with [The enemy stands there and does nothing](https://rigbak.com/docs/soulslike-combat/troubleshooting#the-enemy-stands-there-and-does-nothing).

---

## Debug it

Press Play and turn the overlays on. Each writes a block above the pawn it belongs to.

```
SEC.Debug.Role 1        // Name and combat role, colored by role
SEC.Debug.Decision 1    // Distance, angle, line of sight, speed, threat
SEC.Debug.Scoring 1     // What each action scored, highest first
SEC.Debug.Movement 1    // Movement layer, strafe side, heading
SEC.Debug.Awareness 1   // Awareness state, meter, age of the last known location
```

`SEC.Debug.All 1` turns every block on at once. `SEC.Debug.WatchPawn <name>` narrows them to one enemy (part of a name is enough, and the console names which pawn it picked), and `SEC.Debug.WatchClear` puts them all back.

Twelve sections exist: **Role**, **Decision**, **Movement**, **Awareness**, **Territory**, **Actions**, **Reactions**, **Scoring**, **Tokens**, **Vitals**, **Teams** and **Approach**. Each takes `1` or `0`.

For a record you can scroll back through, switch the logs on instead.

| Console variable | Prints |
| --- | --- |
| `SEC.Debug.LogActionDecisions` | Why each action scored what it did, and what refused the rest |
| `SEC.Debug.LogActionExecution` | Action starts, ends and cooldowns |
| `SEC.Debug.LogReactions` | Which trigger rule answered an event, and with what |
| `SEC.Debug.LogRoleAssignments` | Role assignment (`2` for verbose) |
| `SEC.Debug.Movement.LogMovement` | Layer switches, pathfinding, stuck, detour |
| `SEC.Debug.Threat.Log` | Threat events |

The Output Log holds only problems to fix until you ask for more. `SEC.Logs Verbose` raises every SEC category at once, `SEC.Logs` alone puts the quiet default back, and `Log LogSECMovement Verbose` raises one system. Each system has its own category: `LogSECActions`, `LogSECReactions`, `LogSECMovement`, `LogSECRoles`, `LogSECTokens`, `LogSECThreat`, `LogSECAwareness`, `LogSECTerritory`, `LogSECBrain`, `LogSECEquipment`, `LogSECEncounter`, `LogSECWorldTags` and `LogSoulslikeEnemyCombat`, with `LogSECCore`, `LogSECVitals`, `LogSECDamage`, `LogSECDefense`, `LogSECAnim`, `LogSECTelegraph` and `LogSECApproach` for the combat layer.

The world drawings cover what you need to see in the level rather than read.

| Console variable | Draws |
| --- | --- |
| `SEC.Debug.Movement.DrawScoring` | The sampled directions, red low to green high |
| `SEC.Debug.Movement.DrawNav` | Navmesh validity and the ledge guard |
| `SEC.Debug.Movement.DrawAvoidance` | Avoidance radii and the pawns being avoided |
| `SEC.Debug.Melee.DrawTracing` | The swept shapes of a weapon trace |
| `SEC.Debug.Stimulus.Draw` | Telegraphs going out |
| `SEC.Debug.Steering.Draw` | Motion warps and approach windows |
| `SEC.Debug.Threat.Draw` | Threat cone, progress arc, color grading |

> **Note**
>
> **Decision**, **Movement**, **Scoring**, **Awareness**, **Territory**, **Tokens** and **Approach** are worked out on the server and draw only there. **Role**, **Actions**, **Reactions**, **Vitals** and **Teams** replicate, so they read on a client too.

<details>
<summary>Debug one enemy from the Details panel (Advanced)</summary>

Each of the twelve overlay sections has a **Debug Overlay** checkbox on the component it reads from, and ticking one there affects that enemy alone. The movement, action, threat and reaction logs and world drawings sit beside them as checkboxes too. The remaining console switches are global only.

**Details panel: Action Evaluation Component** (component, in AEnemyControllerBase)

**Category: Debug**

| Property | Value |
| --- | --- |
| Debug Log Decisions | false |
| Debug Log Execution | false |

*Component flags OR matching SEC.Debug.* console variables enable the same logs.*

**Details panel: Movement Evaluator Component** (component, in AEnemyControllerBase)

**Category: Movement Evaluator > Debug > Draw**

| Property | Value |
| --- | --- |
| Debug Draw Scoring | false |
| Debug Draw Avoidance | false |
| Debug Draw Nav | false |

**Category: Movement Evaluator > Debug > Log**

| Property | Value |
| --- | --- |
| Debug Log Movement | false |
| Debug Log Tick | false |
| Debug Log Scoring | false |
| Debug Log Avoidance | false |
| Debug Log Strafe Swap | false |
| Debug Log Strafe State | false |

*Component flags OR matching SEC.Debug.Movement.* console variables enable the same output.*

They are readable and writable from Blueprint, so a debug menu can drive them at runtime.

`SEC.Debug.ScoringRows` sets how many rows the score list keeps, 5 by default and 0 for all of them. `SEC.Debug.MaxDistance` (4000 cm) sets how far from the camera a block still draws, and `SEC.Debug.TextScale` sizes the text.

The per-tick movement stream runs on an enemy while either its **Debug Log Tick** box or the console switch is on.

```
SEC.Debug.Movement.LogTick 1      // Per-tick stream on for every enemy
SEC.Debug.Movement.LogTick 0      // Undoes the line above and nothing more
```

When the stream floods the console after `LogTick 0`, an enemy has **Debug Log Tick** ticked. Untick it on that enemy.

</details>

---

## Nothing happens

### The enemy stands there and does nothing

No combat target, or the enemy never reached its combat phase. Check these five in order.

1. **AI Controller Class names another controller** on the pawn Blueprint. Enemy Character Base ships set to **Enemy Controller Base**; a controller not made from it, such as the engine's **AIController**, carries none of the combat components. Set it back in Class Defaults.
2. **Target Selector is empty** on the Enemy AI Config. An empty one still takes the first target the enemy may fight, so this rarely leaves a single enemy idle, but it gives you no say in which target it takes. Set it to **Awareness Filtered Target Selector** and leave its **Inner Selector** empty, so it offers the nearest target this enemy has perceived. **Closest Target Selector** works too, though it picks anything registered, sensed or not; the built-in brain still waits to fight a target until the enemy senses it.
3. **Awareness Config is empty** on the Enemy AI Config. The enemy senses nothing, so it never adds you to its targets on its own. The built-in brain still fights a target that reaches it through step 4; a StateTree that gates its combat on the **Awareness State At Least** condition holds at Unknown and never enters combat. Point it at an Awareness Config asset and leave that asset's defaults alone. This config does the perceiving; the filtered selector in step 2 is what turns perception into aggro, so fill in both.
4. **Nothing put the player in the target pool.** An enemy adds a target once it detects it. To have the fight start without that, on the player pawn's **Event BeginPlay**, branch on **Has Authority**, then call **Register Combat Target** on the **AICombat Role Subsystem** with **Target Actor** set to **Self**. See [Getting Started](https://rigbak.com/docs/soulslike-combat/getting-started).
5. **AI Config is empty on the pawn.** On **Enemy Character Base** the pawn's **AI Config** is the one read, even when empty, so the controller's **Default AI Config** never backs it up. That controller field counts only for a pawn that provides no config of its own.

`SEC.Debug.Role 1` reads `None` for an enemy that never took a target. No block above the pawn at all means it carries no SEC components, which points at the first cause.

### It moves but never attacks

Something refuses every action before it scores.

Run `SEC.Debug.Scoring 1`. An action a hard gate refused prints the reason in place of a score. The usual reasons:

| Reason | Fix |
| --- | --- |
| **Enabled** unticked on the action | Tick it. Unticking it also stops the ability being granted. |
| **Selection** is **Manual Only** | That action waits for a direct **Execute Action** call. Set Selection to Scored for a scored move. |
| **Selection** is **Chain Only** | Nothing chains into it, or the chain window has closed. Wire a chain into it from another action, or set Selection to Scored. |
| On cooldown, or **Max Consecutive Uses** spent | Expected. Give the enemy a second action to switch to. |
| **Recovery** | The gap after any action. The three **Recovery** fields on the AI Config ship at 0, so this holds nothing back until one of them carries a value. |
| A gate said no | A **Combat Token Gate** on a full pool, or a **Stamina Gate** under its minimum. |
| **Requires Tags** or **Block Tags** | The enemy, the target or the world does not hold the right tags. |
| **Require Line Of Sight** ticked | The world blocks the view to the target. Characters, and anything they hold, do not. |
| `SEC.Action.BlockActions` | That tag sits on the enemy's ability system component. Something added it and never removed it. |

### It scores and wins, but nothing happens

The action starts something that does nothing.

- **The ability has no activation graph.** An ability implementing neither **Activate Ability** nor **Activate Ability From Event** starts and never ends.
- **The Montage Payload has no montage.** Saving the Action Set reports this in the **Asset Check** message log.
- **The Action ID is empty.** An action added through the Details panel array instead of the canvas has no ID, wins the poll, then gets discarded silently. Opening the asset on its canvas repairs it.
- **Manage Action Sets Automatically is unticked** on the AI Config, which applies nothing at all.

### A revived or pooled enemy never acts again

Death holds a block on action evaluation, and only a revive releases it.

Call **Handle Revive** 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, since death released it.

---

## Attacks

### It swings from across the room

The action has no **Distance Scorer**, so it has no opinion about distance.

Open the Action Set, and on the card's **Scoring > Scorers** list add a **Distance Scorer**. Its **Range** defaults to a melee band peaking between 100 and 250 cm. A brand new action ships with no scorers at all, which is what lets it fire at any range. See [Action System](https://rigbak.com/docs/soulslike-combat/action-system).

### It attacks once and then freezes

The ability the action started never ends, so the action waits on it.

- Give the ability a path that reaches **End Ability** on completion, on cancel and on interrupt. An ability playing a montage through **Play Montage and Wait** ends when the montage does.
- Set **Ability Timeout** on the action's execution method, behind the advanced arrow, to bound the wait.
- For an ability meant to keep running, pick the **Gameplay Ability (Fire And Forget)** execution method so the action finishes in the same frame.

A 30 second safety limit forces completion either way and names the action that hit it.

### It pauses too long between attacks

Recovery holds offensive actions back after any one of them ends, while movement and reactions keep running.

Tune it on the Enemy AI Config under **Recovery**.

| Field | Sets |
| --- | --- |
| **Action Recovery Time** | Seconds held off after an action completes. |
| **Interrupt Recovery Time** | Seconds held off after an action is interrupted or canceled. Keep it shorter than the above. |
| **Action Recovery Time Randomization** | Jitter on the completion window. |

All three at 0 turns recovery off. To override it for one move, tick **Override Recovery Time** on that action and set **Recovery Time**, which replaces the global value rather than adding to it. `SEC.Debug.LogActionDecisions 1` prints `Recovering (X.Xs remaining)` while the gate holds.

### The whole pack swings at once

The attacks carry no **Combat Token Gate**, so nothing caps how many enemies act on one target.

Add a **Combat Token Gate** to each attack, then set the pool size under **Combat Tokens** in Project Settings. Two token tags ship with a **Budget** of 2 each. See [Combat Tokens](https://rigbak.com/docs/soulslike-combat/combat-tokens).

Two things quietly defeat it. A token tag with no row in Project Settings hands out unlimited slots, and an enemy with no focus target claims nothing and runs uncapped. `SEC.Debug.Tokens 1` writes the pool above the head of the target the slots belong to, rather than above an attacker, and prints `unlimited` in place of a count for the first case.

### An attack lands but deals no damage

Read the Output Log first. The trace component names most of these itself.

| Check | What to look for |
| --- | --- |
| **Socket IDs** | The IDs on the melee trace notify match **Trace Sockets** on the weapon exactly. A window naming a socket nothing registered says so in the log. |
| **Trace Filter** | In **Channel** mode, the channel the target blocks. In **Object Types** mode, the type the target belongs to. Turn on `SEC.Debug.Melee.DrawTracing 1` and watch the sweep. |
| **Damage Config** | **Default Damage Config** on the trace component, or **Damage Config** on the notify. Damage does not come from the weapon actor class. |
| **The target answers damage** | It implements the SEC Damageable interface (reparenting to **Enemy Character Base** covers this), or handles **Event Any Damage**, which the sweep falls back to. |
| **A sensor in the way** | A component that blocks the trace channel stops the sweep before it reaches the body behind it. Set that component's response to the trace channel to **Overlap**. |

See [Melee Trace](https://rigbak.com/docs/soulslike-combat/melee-trace).

---

## Movement

### It does not move at all

Six causes, in the order worth checking.

- **No focus actor.** Nothing registered a combat target, so there is nothing to move relative to. This is the common one and it logs nothing.
- **The Movement Evaluator sits on the pawn.** It belongs on the AI controller. On a pawn it warns once at BeginPlay and then does nothing.
- **No navmesh.** Past 800 cm the enemy asks for a path, the request fails, and the enemy asks again about every 0.25 seconds without closing the gap. Add a **NavMesh Bounds Volume**, build navigation, and press **P** in the viewport to check it covers the floor. On a large or open world map, see [the navmesh is empty on a large map](https://rigbak.com/docs/soulslike-combat/troubleshooting#the-navmesh-is-empty-on-a-large-map) below.
- **A leftover `SEC.State.IsMovementBlocked` tag** on the enemy's ability system component freezes it outright. It ships in a new action's **Add Tags** and is meant to clear when the action ends.
- **Apply Movement Input is off** on the Movement Evaluator, which is evaluate-only mode.
- **The AI Movement task is not running.** In a StateTree graph it has to stay in a running state through combat. See [StateTree Integration](https://rigbak.com/docs/soulslike-combat/statetree).

> **Warning**
>
> The first Play In Editor after opening a project can start before navigation finishes building, and a game world never fills a tile the editor world had not reached. An enemy that pathfinds on the second Play and not the first has hit this. **Build > Build Paths** and save the map.

### The navmesh is empty on a large map

An open world, or any level using **Dynamic** navmesh generation, builds navigation around invokers rather than everywhere at once. With no invoker in the level nothing asks for a tile, so the navmesh stays empty and every enemy past 800 cm fails its path request. Pressing **P** shows bare ground.

Add a **Navigation Invoker** component to the actors navigation should follow, the player pawn first. Each one asks for tiles within its generation radius and lets them go past its removal radius.

Add it to the enemies as well when they wander far from the player, since an enemy outside every invoker's radius stands on unbuilt ground. Set **Runtime Generation** to **Dynamic** in **Project Settings > Navigation Mesh** for invokers to have anything to drive.

### It grinds against a wall

The target sits behind cover. The straight-line distance stays short while the walking route is long, so tactical steering pushes into the geometry.

Detour escalation catches this and hands off to pathfinding to round the corner. Check on the Movement Evaluator, under **Hybrid Movement > Detour**:

- **Enable Detour Escalation** is on (it ships on).
- The navmesh offers a route around the obstacle.
- Lower **Detour Enter Ratio** (default 1.6, try 1.4) or **Detour Min Excess** (default 200 cm) when a real detour still reads as minor.
- **Detour Escalate on Stall** is on for tight corners. Raise **Detour Stall Speed** (60 cm/s) if a slow grind does not register.

`SEC.Debug.Movement.LogMovement 1` prints each recheck as `ENGAGE`, `HOLD` or `release`. See [Movement System](https://rigbak.com/docs/soulslike-combat/movement-system#two-layers-and-rounding-corners).

### A Waiter or Flanker freezes after the player jumps a gap

The player is close in a straight line while the walkable route wraps around the pit, and a Waiter or Flanker can already be inside its band, so steering idles at the rim with sight clear across the gap.

- Leave **Detour Use Line Of Sight Pre Gate** on. It reads the navmesh along the straight line, so a gap engages the detour even with sight clear.
- Check both sides of the gap sit on connected navmesh. A route that stops at the rim means no walkable way across, and staying tactical is the right answer.
- Lower **Detour Release Ratio** (default 1.35) only if the enemy gives up the route too early on a short way around.

`SEC.Debug.Movement.LogMovement 1` prints `Detour eval: skip (no reachable route)` when the far side is not connected.

### It jogs instead of running while closing in

Sideways movement costs speed, and direction scoring angles the approach a few degrees while the enemy holds a strafe side or steps around a neighbor.

Raise **Strafe Free Angle** on the Movement Evaluator (15 degrees), the band around straight ahead that costs nothing. **Strafe Speed Penalty** (0.75) softens the cost everywhere including real circling, and 0 turns it off. Check the run window in your locomotion graph too, since a 30 degree approach keeps most of its speed by design. See [Movement System](https://rigbak.com/docs/soulslike-combat/movement-system#strafe-animations-at-full-speed).

### It walks off a ledge or into a hazard

The navmesh ends past the visual drop, or the hazard is painted as cost rather than as an area to avoid.

- Press **P** and check where the navmesh stops.
- **Enable Nav Aware Sampling** is on and **Nav Score Weight** is above 0.
- For a patch the enemy can walk on but should not, add the nav area to **Hazard Area Avoidance** on the Movement Evaluator with a strength around 0.75, where 0 ignores it and 1 scores it like a wall. High nav cost alone still reads as walkable at close range.
- Tune **Nav Probe Distance** (120 cm): lower in tight spaces, higher for fast movers.

`SEC.Debug.Movement.DrawNav 1` marks blocked directions with blue spheres. See [Movement System](https://rigbak.com/docs/soulslike-combat/movement-system#staying-off-ledges-and-avoiding-hazards).

### It walks home in the middle of a fight

Its territory leash broke, or it refuses a target standing outside the leash.

On the pawn's **SEC Territory** component, under **Leash**:

- **Leash Enabled** ships off. Something turned it on.
- **Leash Radius** (2000 cm) is measured straight from the anchor, so a radius tighter than the wander area reads as broken while the enemy drifts.
- **Only Fight Inside Leash** is on by default, so a target beyond the ring is ignored outright. Untick it for an enemy that charges anything it notices and gets dragged home instead.
- **Leash Break Grace Time** (2 s) is how long it may stay out before it gives up. 0 turns for home the moment the line is crossed.

`SEC.Debug.Territory 1` draws the boundary and prints how far the leash is from breaking. See [Territory](https://rigbak.com/docs/soulslike-combat/territory).

---

## Reactions and animation

### It never parries or dodges

Nothing announced the attack, so no trigger rule ever ran.

1. Put a **SEC Telegraph Window** over the wind-up in the attacker's montage. Without it no stimulus goes out and the enemy stands there taking hits.
2. Give the Reaction Set a **Trigger Rule** whose **On Stimulus** matches the event, wired to at least one reaction.
3. Check the enemy has a Reaction Set at all, through **Default Reaction Set** on the AI Config.

`SEC.Debug.Stimulus.Draw 1` shows whether anything is going out. `SEC.Debug.LogReactions 1` names the rule that answered, or prints `answered by nothing` with the rule count it walked. See [Reaction System](https://rigbak.com/docs/soulslike-combat/reaction-system).

### A behavior tree action starts nothing

The blackboard has no key for the action's payload, so the tree receives nothing to act on. A write to a missing key is dropped by the engine, and the log names the key once per blackboard.

Add these keys to the blackboard asset:

| Key | Type | Base Class |
| --- | --- | --- |
| `SEC_Payload` | Object | **Execution Payload** |
| `SEC_ActionId` | Name |  |
| `SEC_TargetActor` | Object |  |
| `SEC_SelfActor` | Object |  |
| `SEC_Distance` | Float |  |

Then point **Payload Key Name** on the action's execution method at `SEC_Payload`. `BB_SEC_Basic` in the demo content declares `SEC_Payload`, `SEC_ActionId`, `SEC_TargetActor` and `SEC_Distance` already, so build on it or copy it.

### A very short trace window misses on an enemy nobody can see

An enemy nobody draws, such as one behind the camera in a single-player game or on a listen server, leaves its bones as they were until a trace window opens. **SEC Melee Trace** keeps the mesh refreshing for the length of the window, but a window that opens on such a mesh starts sweeping a frame later, since the mesh still shows an older pose. A window only a frame or two long can sweep little or nothing.

Lengthen the window by a frame or two. On a dedicated server, **Enemy Character Base** keeps its mesh refreshing all the time, so its windows sweep from their first frame.

### The log warns that something else bound Process Root Motion Post Convert To World

Something in the project bound character movement's **Process Root Motion Post Convert To World** after **SEC Approach** had taken it. That step holds one binding, so the approach took it back and hands each move on to the other binding, and both run. The warning comes once per class and play session.

Bind the other step before the approach component begins play, and the approach chains it from the start without a warning. See [Animation Integration](https://rigbak.com/docs/soulslike-combat/animation-integration#steer-an-attack-toward-its-target).

---

## Packaging

### A packaged build fails with "Missing Dependency GameplayAbilities"

Unreal does not stage an engine plugin your project depends on only through another plugin.

Open your `.uproject` and, in its `Plugins` list (add the list if the file has none), add an entry for each of the six engine plugins SEC needs: `GameplayAbilities`, `StateTree`, `GameplayStateTree`, `MotionWarping`, `AnimationWarping` and `EnhancedInput`. Each entry sets `Enabled` and lists the platforms you ship. Where the file already lists one of them, add the platforms to that entry.

```json
{
    "Name": "GameplayAbilities",
    "Enabled": true,
    "SupportedTargetPlatforms": [
        "Win64"
    ]
}
```

The alternative is `Config/DefaultGame.ini`, under `[/Script/UnrealEd.ProjectPackagingSettings]`:

```ini
+DirectoriesToAlwaysStageAsNonUFS=(Path="Engine/Plugins/Runtime/GameplayAbilities")
+DirectoriesToAlwaysStageAsNonUFS=(Path="Engine/Plugins/Runtime/StateTree")
+DirectoriesToAlwaysStageAsNonUFS=(Path="Engine/Plugins/Runtime/GameplayStateTree")
+DirectoriesToAlwaysStageAsNonUFS=(Path="Engine/Plugins/Animation/MotionWarping")
+DirectoriesToAlwaysStageAsNonUFS=(Path="Engine/Plugins/Animation/AnimationWarping")
+DirectoriesToAlwaysStageAsNonUFS=(Path="Engine/Plugins/EnhancedInput")
```

---

## FAQ

<details>
<summary>Can I use this with a character I already have?</summary>

Reparent it rather than rebuilding it. **File > Reparent Blueprint**, then pick **Enemy Character Base** for the pawn and **Enemy Controller Base** for the controller. Your existing components, variables and graphs stay, and you inherit the ability system, the combat components and the damage interfaces. Delete any duplicate the Blueprint added itself, such as its own ability system component.

Adding the components to a bare AI controller is not equivalent. The base controller holds the AI's facing during an attack and turns it toward a target's last-known location, and attack abilities rely on that.

</details>

<details>
<summary>Does this work in multiplayer?</summary>

Yes, on a listen server and on a dedicated server. AI decisions run on the server. Vitals, action and reaction execution state, combat roles and the active sets replicate to clients. See [Multiplayer](https://rigbak.com/docs/soulslike-combat/multiplayer).

</details>

<details>
<summary>How much of this needs GAS?</summary>

Melee traces and the damage path resolve without an ability system on either actor: a target that implements the damage interface answers directly, and anything else falls back to engine point damage. Running actions and reactions through the Gameplay Ability execution methods needs one, since that is where blocking tags, cooldowns and the end-of-ability signal come from. The plugin lists **GameplayAbilities** as a dependency either way.

</details>

<details>
<summary>How do I handle death: ragdoll, weapon drop, dissolve?</summary>

Call **Handle Death** on the **SEC Combat Controller** component. It stops the brain, cancels the running action and reaction, stops melee tracing, disables threat detection, unregisters the enemy from the role system, clears focus, and fires **On Death**. The pawn is then safe for ragdoll, dissolve or destroy; none of that happens on its own.

**Drop Weapon on Death** is on by default and releases everything the pawn holds with **Drop**, which asks each item to drop itself and to stay for the equipment component's **Drop Lifetime**. Untick it to release with **Leave In World** instead, which detaches each item and leaves it standing where it was.

**Auto Handle Death on Health Depleted** is on by default, so an emptied health vital runs the shutdown without a call from you.

</details>

<details>
<summary>Which engine versions, and does source ship?</summary>

Version 3.2.0 runs on Unreal Engine 5.6, 5.7 and 5.8. Full C++ source ships with the plugin.

</details>

---

## Support

**Purchase and updates:** [Fab](https://www.fab.com/listings/7087cec0-6975-4de5-82e0-0de0b9b3e9a7)

**Questions, bugs and feature requests:** [Discord](https://discord.com/invite/CbRcTsYQcz), or the Fab product page.

---

Previous page: [Patterns & Examples](https://rigbak.com/docs/soulslike-combat/patterns). Next page: [Performance](https://rigbak.com/docs/soulslike-combat/performance)
