# Animation Integration

> Author combat timing on the animation itself: hold a gameplay tag for a montage window, mirror it into an animation Blueprint bool, and steer an attack toward its target.

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

> Timing that belongs to the animation, authored on the animation. A montage window holds a gameplay tag while it runs, and the rest of the game reads that tag.

## Set it up (45 seconds)

1. **Put a state tag window on the montage**

   Open the dodge montage, right-click a notify track, **Add Notify State**, **SEC State Tag Window**. Drag it across the frames the state should cover and fill **Tags**.

   In **AM_Dodge_Roll**, under State Tags, set:

   | Property | Value |
   | --- | --- |
   | Tags | SEC.State.Intangible |

   *The track reads State Tag [SEC.State.Intangible], so the window says what it holds.*
2. **Reparent the animation Blueprint**

   Open the pawn's animation Blueprint, **Class Settings**, and set **Parent Class** to **SEC Anim Instance Base**.
3. **Map the tag to a bool**

   Add a bool variable, `IsDodging`. Then open **Class Defaults** and add a row to **Gameplay Tag Property Map**, naming the tag and picking that variable.

   In **ABP_Enemy**, under Gameplay Tags, set:

   | Property | Value |
   | --- | --- |
   | Tag to Map | SEC.State.Intangible |
   | Property to Edit | IsDodging |

   *The bool tracks the tag for as long as the window holds it, with no event graph nodes.*
4. **Play, and watch it work**

   Roll, and the bool flips on for the window and off at its end. An enemy sweep crossing those frames lands nothing and keeps traveling, because a melee trace carries `SEC.State.Intangible` in its **Pass Through Tags** by default.

   `AM_SEC_DodgeBack` in the demo content ships with the window already on it.

> **Warning**
>
> Tags live on the pawn's **Ability System Component**. A pawn without one has nowhere to put them, so the window holds nothing and the bool never flips. **Enemy Character Base** creates one; a custom pawn needs one added. Give the window a positive duration as well, since a zero-length window opens and closes on the same frame.

---

## Hold a tag for part of an animation

**SEC State Tag Window** has one field. **Tags** names what the owner holds while the window runs, and empty applies nothing.

Because the timing lives on the montage, retiming the animation moves the window with it. An interrupted montage releases its tags too: a canceled dodge drops its invulnerability rather than stranding it.

Overlapping windows compose. Two windows holding the same tag keep it until the second one closes.

These tags ship as starting points. The plugin adds none of them by itself; your montages do.

| Tag | Author it on |
| --- | --- |
| `SEC.State.Intangible` | The i-frames of a dodge or roll. The one tag combat code reads on its own, through **Pass Through Tags** on a melee trace. |
| `SEC.State.Dodging` | The whole roll, for the movement slowdown below. |
| `SEC.State.Blocking` | A raised guard, for the slow walk it costs. |
| `SEC.State.Staggered` | The reaction montage after a hit lands. |
| `SEC.State.Recovering` | The recovery section of an attack, to gate other actions through **Requires Tags** and **Block Tags**. |
| `SEC.State.Sprinting` | A sprint, with a speed multiplier above 1. |

Author your own for a parry window, a hyper-armor stretch, or anything else your project needs. A tag is a name; what it means is up to the code that reads it.

> **Note**
>
> For the attack itself to deal damage, the montage also needs a **SEC Melee Trace Window** over the swing frames. See [Melee Trace](https://rigbak.com/docs/soulslike-combat/melee-trace).

A **SEC Telegraph Window** holds tags the same way, and warns the enemies standing in front of it at the same time. Reach for it on an attack wind-up, or on a state an enemy should get to answer. For a stretch nobody answers, the state tag window is the smaller tool. See [Telegraphs](https://rigbak.com/docs/soulslike-combat/attack-telegraphs).

---

## Invulnerability frames

A window holding `SEC.State.Intangible` is the whole setup. A sweep reaching a target that holds it drops the contact: no damage, no impact effect, and the swing is not spent, so it carries on to whatever stands behind and can land on the same target once the window closes.

Nothing needs setting on the attacker. A melee trace component ships with that tag in **Pass Through Tags**.

For a dodge that costs the attacker their swing, the way a parry does, resolve the hit in the pawn's own damage handling instead and leave the tag out of **Pass Through Tags**. [Melee Trace](https://rigbak.com/docs/soulslike-combat/melee-trace) covers the difference between a hit that passes through and one that resolves.

---

## Mirror a tag into an animation bool

**SEC Anim Instance Base** keeps a Blueprint bool in step with a gameplay tag. One row in **Gameplay Tag Property Map** per pair, then read the bool in a state machine, a blend, or an animation layer.

Loose tags and tags granted by a Gameplay Effect both drive it, so the same bool covers a montage window and a buff.

Binding needs no setup. The animation instance looks for the owner's ability system each frame until it finds one, which covers a pawn that builds its ability system as a Blueprint component and a pawn that builds one later still. To point the map at an ability system the pawn does not carry, such as one living on a Player State, call **Initialize with Ability System** on the animation instance.

---

## Fire a one-off signal from a frame

Some moments need no window and no state: a pose snapshot, a prop spawn, a camera shake. Add **Notify**, **SEC Gameplay Event** at the frame, and set **Event Tag**.

Wait on that exact tag from an ability, or from a Blueprint through **Wait Gameplay Event**. Nothing is added to the pawn and nothing is taken off afterward, so a listener bound after the frame has passed hears nothing. `AM_SEC_Unarmed_Combo` uses one.

The pawn needs an ability system to receive it. A pawn without one names itself in the Output Log and nothing is sent.

> **Tip: Readable notify tracks**
>
> The track shows the tag's last segment, so an event tag ending in PoseSnapshot reads as PoseSnapshot. Several stay legible side by side on one timeline.

<details>
<summary>What the event carries (Advanced)</summary>

The pawn is named as both the event's instigator and its target, and the animation it came from arrives as **Optional Object**. A handler bound to one tag that several montages send reads that to tell which montage fired it.

</details>

---

## Ask the character for its own effect

A footstep sounds different under a barefoot rogue and a plated knight, and authoring that per character means authoring the animation twice. Two notifies ask the character instead, and the character answers.

| Notify | Use it for |
| --- | --- |
| **SEC Play Anim Effect** | A single frame: a footstep, a landing, gear rustling. |
| **SEC Anim Effect Window** | A stretch: a weapon trail, a charge glow, a sustained whoosh. The window opens at the first frame and closes at the last. |

Both carry **Effect Tags**, what the frame asks for, and **Socket Name**, where on the body it belongs. Leave the socket as None and the effect sits at the mesh's own position.

To answer, add the **SEC Anim Effect Handler** interface to the pawn, or to any component it carries, and implement **Handle Anim Effect** (plus **Handle Anim Effect Begin** and **Handle Anim Effect End** for a window). Spawn the Niagara system, play the sound, whatever the effect is. A pawn that answers nowhere does nothing at all.

These tags ship, and a handler asking for a parent tag catches every tag beneath it.

| Tag | Frame it belongs on |
| --- | --- |
| `SEC.AnimEffect.Footstep.Left` / `.Right` | The foot-plant frames of a walk or run. |
| `SEC.AnimEffect.Land` | The landing frame after a fall. |
| `SEC.AnimEffect.WeaponTrail` | The swing frames a trail should cross. `AM_SEC_TwoHanded_SingleAttack` has one. |
| `SEC.AnimEffect.Foley` | Wherever cloth, armor or gear should move. |

> **Note**
>
> A weapon trail is authored by the pawn passing the same call on to whatever it has equipped, which runs its own trail. Each handler on the actor is called once, so a handler does not pass a request to another handler on the same actor.

<details>
<summary>Which machines run an effect (Multiplayer)</summary>

Nothing replicates and nothing runs on a dedicated server. The notify fires on each machine playing the animation, which is where the effect is wanted.

An animation cut short mid-window can leave the close uncalled, so stop anything expensive on the pawn's own teardown as well.

</details>

---

## Steer an attack toward its target

An attack animated on the spot whiffs the moment its target steps aside. **SEC Approach Window** turns the character toward what it is fighting and glides it into range across the frames you mark, then stops a set distance short so the swing lands.

Add **Notify State**, **SEC Approach Window** over the wind-up frames. On an enemy attack that is the whole setup: the enemy character carries a **SEC Approach** component, and an SEC ability stores its target under the same name the window looks for. `AM_SEC_TwoHanded_SingleAttack` has one authored.

**Details panel: SEC Approach Window** (anim notify, in AM_SEC_TwoHanded_SingleAttack)

**Category: Approach**

| Property | Value |
| --- | --- |
| Move by Offset | false |
| Offset Direction | (-1, 0, 0) (greyed out) |
| Offset Distance | 50 (greyed out) |
| Approach Target Name | Target |
| Mode | Move and Face |
| Stop Distance Override | -1 (advanced) |
| Max Approach Distance Override | -1 (advanced) |
| Facing Interp Speed Override | -1 (advanced) |
| Facing Speed by Angle Override | None (advanced) |
| Override Speed Limit | false (advanced) |
| Speed Limit Override | Unlimited (advanced, greyed out) |
| Max Approach Speed Override | 600 (advanced, greyed out) |
| Override Block Movement Input | false (advanced) |
| Block Movement Input Override | false (advanced, greyed out) |
| Override Moving Target | false (advanced) |
| Moving Target Override | Lead (advanced, greyed out) |
| Lead Strength Override | -1 (advanced) |
| Time Mapping Curve Override | None (advanced) |

*Dragged across the wind-up frames. Approach Target Name picks which stored target it steers toward, or Move by Offset steps a set distance instead. Every override left at -1 takes the value on that target, then the matching Default on the Approach component.*

**Mode** picks which half runs.

| Mode | What it does |
| --- | --- |
| **Move and Face** | Glides toward the target and turns to face it. The gap-close for an in-place attack. |
| **Face Only** | Turns to face without moving, for an attack that aims and stays put. |
| **Move Only** | Glides without turning, for a lunge that keeps the direction the animation gives it. |

**Move by Offset** replaces the target entirely. Tick it and the window steps the character a set distance along a direction of its own: **Offset Direction** `(-1, 0, 0)` with **Offset Distance** 50 is a step straight back, whatever way the character faces. Nothing has to be stored for it, and the target fields gray out. It suits a hit reaction or a block that should knock the character back over the animation's own frames.

An attack whose animation already carries root motion travels on its own, and the window makes up only the distance it falls short by, so a window on one of those lands its hit too. On a character a player controls, reach for **Motion Warping** instead: it bends the motion the animator authored rather than adding to it, and it predicts through the ability playing the montage.

> **Note**
>
> Motion Warping is the alternative to the approach window rather than a companion to it, so a character wants one or the other on a given attack. Taking that route means adding a **Motion Warping** component to the character yourself: the enemy character does not ship with one. Without it, a montage's warp window plays on the spot, and an ability built on **Gameplay Ability Base** warns once per enemy class in the log. See [Motion warping](https://rigbak.com/docs/soulslike-combat/action-system#motion-warping-steering-an-attack-toward-the-target).

### Pointing a window at a target

What a window steers toward comes out of a named slot on the character's **SEC Approach** component, the same handover Motion Warping uses for its warp targets. Something stores the target; the animation decides when the steering happens.

An SEC ability stores it on activation under the name in its **Motion Warping Target Name**, which defaults to `Target`, and so does the window's **Approach Target Name**. Matching those two names is what makes an attack steer at the right thing.

From a Blueprint graph, **Set Approach Target to Actor** stores an actor under a name, **Set Approach Target to Location** stores a spot, **Set Approach Target** takes the whole struct when you want per-target distances on it, and **Remove Approach Target** clears one. A window whose name holds nothing plays the attack where the character stands. The window follows its name for as long as it runs: a target stored under it partway through takes over from where the character stands, and clearing the name stops the steering.

The distance and facing overrides on the window can be left at -1, which hands the choice to the stored target, then to the matching **Default** on the Approach component: **Default Stop Distance** 150 cm, **Default Max Approach Distance** 750 cm, **Default Facing Interp Speed** 12. Past the max approach distance the window turns the character toward its target without closing on it, so the attack plays where the character stands.

> **Warning**
>
> **Speed Limit** on the Approach component is **Unlimited**, so a window covers whatever distance separates the two in the span it was given, which can cross a room in a fraction of a second. Set it to **Character's Max Speed** for a gap-close that reads like running, or to **Fixed Speed** with a **Max Approach Speed** in cm/s.

### Steering without a montage

The same steering runs from Blueprint with no montage or notify involved, for a chase, a scripted reposition, or a boss beat you drive yourself. Get the character's **SEC Approach** component and call:

- **Approach Actor**: turn a character toward an actor for a number of seconds, gliding it into range when the mode asks for it.
- **Approach Location**: turn it toward a spot and glide it there over a number of seconds. The spot is exact, so no stop distance comes off it.
- **Approach Offset**: move it a set distance along a direction of its own, for a step back or a sidestep with nothing to aim at. The direction is in the character's own space, and it defaults to Move Only so a knockback does not turn the character.

These start at once rather than waiting on an animation. Seconds is how long the glide takes as well as how long the call runs, so at or below zero the character turns without gliding and keeps turning until **Stop Approach** stops it.

### Keep Distance

An attack's own root motion, a warp or a glide can carry an enemy into the body it is hitting. **Keep Distance** on the **SEC Approach** component stops the attack short of its target. It is **Off** by default; set it to **On** on the enemy's defaults.

In **SEC Approach**, under SEC > Approach > Keep Distance, set:

| Property | Value |
| --- | --- |
| Keep Distance | On (replaces Off) |

*On holds every attack the stop distance short of its target. Off lets an attack travel as far as its motion carries it.*

- **What counts as an attack.** A montage carrying a **SEC Melee Trace Window**, an **SEC Approach Window** that steers at a stored target, or a **SEC Skew Warp** window, from that montage's start to its end. A dodge, a hit reaction or a stun plays as authored.
- **The target.** The actor the attack stored on the Approach component, which for an enemy is the target an SEC ability stores as it activates: the enemy's focus. It counts while its capsule and the enemy's block each other.
- **The distance.** The **Stop Distance Override** of the approach window or **SEC Skew Warp** window playing at that moment, else **Default Stop Distance**, measured between the two capsules. A window whose override is 0 lets that part of the attack reach contact.
- **What it holds back.** The animation's own root motion, a warp and a window's glide to a spot alike. A move toward the target from inside the distance is held where it is, never pushed back, and a move away or past the target's side goes through whole.

> **Warning**
>
> A **SEC Skew Warp** window that names no **Stop Distance Override** keeps **Default Stop Distance** rather than landing where its warp target was placed. An SEC ability places the warp target **Motion Warping Offset** from the target, center to center, so set **Default Stop Distance** to the gap that leaves between the two capsules, or give each **SEC Skew Warp** window its own override.

The demo enemy, `BP_SEC_EnemyCharacter`, has Keep Distance on, and so do the demo boss and any Blueprint built on the demo enemy, so their swings stop short of the player.

<details>
<summary>Keep Distance on other machines (Multiplayer)</summary>

Keep Distance runs inside the movement update on the server and on the copy of the enemy every other machine shows, and the server sends those copies the target while the attack plays, so against a target standing still every machine stops the enemy in the same place. Set it on the character's defaults: a change made at runtime on one machine reaches no other.

</details>

<details>
<summary>Keeping distance from more than the target (C++)</summary>

A C++ subclass of `USECApproachComponent` answers `GetFallbackStopDistance` to stop at something other than **Default Stop Distance**, such as a weapon's reach, and `GatherKeepDistanceBodies` to keep an attack off other characters besides its target. `GetAttackStopDistance` reads the distance in force for the attack playing now, and `SECApproachMath::TravelBeforeReach` measures how far a move travels before it comes within reach of a point.

</details>

<details>
<summary>The whole request: Begin Approach (Advanced)</summary>

**Begin Approach** takes a whole **SEC Approach Request**, for a move that needs a setting the three calls above leave out. **Window Duration** is how long it lasts in seconds, and 0 turns the character without gliding until **Stop Approach**.

Tick **Until Arrival** for a walk to a spot that lasts as long as it takes rather than a set time. It needs **Use Fixed Destination**, and walks the character onto **Fixed Destination** with its own movement, so it plays its walk. It ends **Completed** once the character stands within **Arrival Radius** and **Arrival Angle** of the spot, and **Unreachable** after **Give Up Seconds**, or after **Stall Seconds** without getting closer; either at 0 never gives up. **On Approach Ended** reports which.

**Montage**, **Window Start**, **Window End** and **Effective Rate** on the request are deprecated. Put an **SEC Approach Window** on the montage instead, or set **Window Duration** for a move with no montage behind it.

</details>

<details>
<summary>Chasing a target that keeps moving (Advanced)</summary>

**Moving Target** on the Approach component decides where a glide aims while the target moves, and a window can override it per attack.

| Setting | Aims at |
| --- | --- |
| **Lead** | Where the target is heading. The default, and the smoothest against a target that keeps moving, since it covers a dodge without lurching. |
| **Chase** | Where the target stands right now. Follows every step, which bunches up whenever the target changes direction. |
| **Committed** | Where the target stood when the window opened. For an attack that commits, so a target that got out of the way is missed. |

**Lead Strength** is how much of the target's own motion a leading glide steers ahead of, from 0 for none to 1 for all of it (the default). Lower it to aim nearer where the target stands, so a target sprinting away is followed rather than cut off.

</details>

<details>
<summary>When the glide stays home (Advanced)</summary>

The turn runs whenever the window does. The glide is the part with conditions on it, and each one leaves the attack playing in place rather than sliding it somewhere wrong.

- The target sits past **Max Approach Distance Override**, so a swing thrown across the arena does not turn into a charge.
- The character is already inside the stop distance, measured between the two capsules rather than the two origins, so a wide enemy stops with room for its own body.
- A speed bound is in force and the target is further than it reaches in the window's span. The character approaches as far as it can and the attack lands short.
- The target is destroyed mid-window. The glide stops rather than traveling to the spot it left behind.
- The montage stops, blends out or is replaced. The window ends with it and hands the facing back.

A window that finds no target in reach plays the attack in place. A C++ subclass of the window that overrides `GetMoveWithoutTarget` steps the enemy a set distance instead, for a swing at empty air.

**Time Mapping Curve Override** eases the travel: X is the window's time from 0 to 1, Y the fraction of the distance covered by then. Author an ease-out for a lunge that arrives soft. Unset takes the curve on the stored target, and glides at a constant rate when that has none either.

</details>

<details>
<summary>Who owns the character's facing (Advanced)</summary>

While the window runs, whatever else turns the character stands down, and gets its settings back when the window closes. Several things can hold the facing at once and release in any order, so a window inside a paired animation composes instead of fighting.

For an enemy, the controller stops writing facing for the length of the window, then resumes tracking. An ability that also sets **Lock AI Rotation** on the same montage composes without error, though the two ask for opposite things: the lock stops the controller aiming, and the window turns the character itself.

A second window opening on a character that is already being steered takes over, so the window that opened last is the one steering. A move already told exactly where to land is the exception: it keeps the character until it gets there.

**Acquire Facing Control** and **Release Facing Control** take the facing for anything else that needs it, and **On Facing Control Changed** fires on both. Bind it from code that writes the character's rotation settings, so it stands down for the window and re-resolves once the facing comes back.

</details>

<details>
<summary>Which machines steer (Multiplayer)</summary>

The turn runs on the server and on a player's own machine, and does nothing on a copy of someone else's character, which receives the motion already resolved.

**The travel has one rule: play the montage on every machine.** Each machine running the window works out its own glide toward the same target, and character movement settles the difference. An AI attack gets this for free, since its montage plays on the server anyway. A montage played on one machine alone is the failure case: that machine glides, the server does not, and the server hauls the character back every frame.

Against a stationary target both machines pick the same landing spot and the motion is smooth. The faster the target moves, the further apart the two spots land, and the difference shows up as a tug.

**Prediction removes that**, and prediction means an ability. Four things have to line up:

1. The pawn carries an **Ability System Component**.
2. The ability's **Net Execution Policy** is **Local Predicted**.
3. The montage plays through the **Play Montage and Wait** ability task. The window borrows the ability the ability system recorded against the montage, and only that task registers one.
4. Section changes go through the ability's **Montage Jump to Section**, so the server jumps to the same section.

A player character gliding without an ability names itself once in the Output Log, so the tug has an explanation rather than looking like a bug.

> **Warning**
>
> A montage played from a Blueprint plays only on the machine that played it. On a client, the server never runs the window at all, so nothing turns or glides there and server-side hit checks read a character facing the wrong way.

An ability's graph runs on the server and on the player's own machine, so a target the ability stores steers both, and the server's answer is the one that lasts. **Replicate**, an advanced pin on **Set Approach Target**, **Set Approach Target to Actor** and **Set Approach Target to Location**, is deprecated, which only the node's tooltip says. It keeps having the server send the target to the player's own machine; leave it off in new graphs and store the target from the ability.

An animation carrying its own root motion moves the character on its own, and character movement closes whatever the animation leaves short inside the same move, so that case predicts the same way.

</details>

---

## Scale movement speed while a tag is held

A character holding full walk speed through a dodge slides out of its own animation. **SEC Speed Modifier** scales walk speed while a tag is held, so the slowdown begins and ends with the animation.

1. Add **SEC Speed Modifier** to the character.
2. Add a row to **Speed Scale by Tag**: the tag, and the multiplier it applies. `SEC.State.Dodging` at `0.2` leaves a fifth of the normal speed, enough to steer a roll without walking out of it.
3. Put a **SEC State Tag Window** across the dodge frames with that same tag in **Tags**.

**Details panel: SEC Speed Modifier** (component, in Character)

**Category: Movement**

| Property | Value |
| --- | --- |
| Speed Scale by Tag | 1 element |
| SEC.State.Dodging | 0.20 |

*Scales walk speed while a tag sits on the owner. Each entry pairs a tag with the multiplier it applies.*

Tags held at the same time multiply, so a 0.5 slow alongside a 0.2 dodge leaves a tenth of the speed. A parent tag in the table matches the tags beneath it, so one row covers a branch. A multiplier above 1 speeds the character up, which is how `SEC.State.Sprinting` uses the same table.

With no tag held, the character walks at its own speed. The table scales the character's own **Max Walk Speed**, along with anything else that sets its walk speed, so set **Max Walk Speed** as usual.

<details>
<summary>Slows that no tag stands for (Advanced)</summary>

Some slows belong to a projectile or a pickup rather than to a montage. **Add Speed Modifier** applies one under an id you pick and holds it until **Remove Speed Modifier** drops that id. Calling it again with the same id replaces that id's multiplier. **Has Speed Modifier** reports what is held, and **Clear Speed Modifiers** drops every id while leaving the tag table alone.

That path needs no ability system component, so it works on a character with no combat systems attached. Ids and tags land in the same pool and multiply together.

**Get Base Max Walk Speed** and **Set Base Max Walk Speed** show as Deprecated and keep working as they did. For an upgrade that raises the character's own walk speed, call **Set Base Value** with **Max Walk Speed** on its **SEC Movement Modifiers** (below).

**Set Speed Scale for Tag** and **Remove Speed Scale for Tag** edit the table while play runs, and the first starts watching a tag the table did not carry. A negative or non-finite multiplier is refused wherever it enters, so one bad row cannot reach the movement component.

</details>

<details>
<summary>Changing movement from your own Blueprint (Advanced)</summary>

**SEC Movement Modifiers** holds every change to the character's walk speed, acceleration, braking, ground friction, turn rate and turning flags. The speed modifier and the approach go through it too, so your changes combine with theirs.

1. Call **Get Movement Modifiers** on the character. It adds the component the first time, so nothing needs adding by hand.
2. Change a setting under a **Source**, any object that stands for your change, usually self:

   - **Override Value** replaces a value while you hold it. The highest **Priority** wins.
   - **Scale Value** multiplies whatever the overrides leave. Every scale multiplies together, and a scale of 1 removes yours.
   - **Override Flag** sets a turning flag, such as **Orient Rotation To Movement**.
3. Call **Remove Modifiers** with the same **Source** when you are done. It removes only what that source held, and the character's own value returns once nothing modifies a setting.

**Set Base Value** changes the character's own value under whatever modifies it, for an upgrade that raises its walk speed. While an override holds that value, the override wins until it goes. A value written straight onto the **Character Movement Component** while something modifies it lasts only until the next change. An approach window holding the facing puts back a turning flag you wrote that way when it ends, and with **Facing Hand Back Rate** set, a turn rate you wrote during the turn back gives way to the rate from before the turn. Change it through **SEC Movement Modifiers** and the character keeps it.

</details>

<details>
<summary>Driving your own movement system (Advanced)</summary>

**On Speed Scale Changed** fires with the combined multiplier whenever it changes. A character with no **Character Movement Component** still tracks tags and still broadcasts, so a project with its own movement code can bind that event and ignore the walk speed side.

Subclass the component in Blueprint to override **Combine Speed Scales**, which decides how several multipliers stack, or **Apply Speed Scale**, which decides what the multiplier drives. Override the second to scale acceleration and rotation rate alongside walk speed.

</details>

<details>
<summary>Keeping speed in step across the network (Multiplayer)</summary>

Walk speed is not a replicated property, so each machine works its own value out from the tags it can see. Add the driving tag through a Gameplay Effect or **Add Replicated Loose Gameplay Tag** so every machine agrees. A tag added with **Add Loose Gameplay Tag** exists only where it was added, which leaves the server and the clients disagreeing about how fast the character moves.

A montage window adds loose tags per machine, and the montage plays on the server too, so a window-driven slow stays consistent without extra work.

</details>

---

## Debug it

```
SEC.Debug.Approach 1            // What each approach window decides, and a block above each character
SEC.Debug.Steering.Draw 1       // Orange is an approach window, green is a motion warp
SEC.Debug.Warp 1                // What an ability's motion warping reach check decides
SEC.Debug.Melee.DrawTracing 1   // The sweeps a melee trace window runs
```

`ShowDebug AbilitySystem` lists the tags a pawn holds right now, which is how you check that a window opened and closed. The **SEC Approach** component also carries a **Debug Overlay Approach** checkbox that turns the approach view on for that one character and needs no console.

<details>
<summary>Reading the steering draw (Advanced)</summary>

Both steering systems draw the same arrangement, which is what makes the color the answer to which one is moving the character. A line runs from the character to where the motion is taking it and a sphere marks that spot, a ring around the target shows how far short of it the motion stops, and a silver line joins the goal to the target. White is the way the character points, magenta the way the motion wants it to point: two arrows half a turn apart means the wrong facing is being asked for rather than the wrong goal being given. On a listen server the two machines draw at different heights, so both are readable at once.

</details>

<details>
<summary>Nothing happens (Advanced)</summary>

| Problem | Likely cause | Fix |
| --- | --- | --- |
| Tag never appears | The pawn has no ability system component | Add one, or derive the pawn from **Enemy Character Base**. |
| Tag never appears | **Tags** left empty on the notify | Fill **Tags**. |
| Tag sticks after the montage | Animation Blueprint recompiled mid-window in Play In Editor | Restart Play In Editor. Unreal skips notify ends while reinstancing Blueprints. |
| Bool never flips | The variable is not mapped, or the row names another tag | Check the row in **Gameplay Tag Property Map**. |
| i-frames ignored on the server | **Trigger on Dedicated Server** cleared on the placed notify | Re-enable it. |
| i-frames ignored on the server | The mesh's **Visibility Based Anim Tick Option** is **Only Tick Pose when Rendered**, and a dedicated server draws nothing | Set it to **Always Tick Pose**, the character default. |
| Nothing answers an effect notify | No handler on the pawn or its components | Add the **SEC Anim Effect Handler** interface and implement it. |
| Attack neither turns nor closes | Nothing stored under the window's **Approach Target Name**, or no **SEC Approach** component on the character | Add the component, and store the target with **Set Approach Target to Actor**. `SEC.Debug.Approach 1` names which one is missing. |
| Attack steers at the wrong thing | The window's **Approach Target Name** and the name the ability or graph writes disagree | Match the two. An SEC ability writes its **Motion Warping Target Name**. |
| Attack turns but stays put | The target is past **Max Approach Distance Override**, or already inside the stop distance | Raise the limit, or lower **Stop Distance Override**. |
| Attack crosses a huge distance instantly | **Speed Limit** is **Unlimited** | Set **Character's Max Speed**, or **Fixed Speed** with a **Max Approach Speed**. |
| The server sees the attack facing the wrong way | The montage plays from a Blueprint, so it never plays on the server | Play the attack through an ability, or play the montage on the server as well. |
| Damage lands during i-frames | The window holds a tag the melee trace does not read | Use `SEC.State.Intangible`, or add your tag to **Pass Through Tags** on the attacker's trace component. |

</details>

<details>
<summary>Windows on a dedicated server (Multiplayer)</summary>

A window runs wherever the montage plays, the server included, and adds loose tags to that machine's ability system component. Nothing replicates, because the server plays the montage too and its own window is what server-side damage checks read.

The server runs a window while the mesh ticks its pose. A character's mesh ticks it whether drawn or not (**Always Tick Pose**, the character default), so a window runs on a dedicated server with nothing to set. **Only Tick Pose when Rendered** in the mesh's **Visibility Based Anim Tick Option** stops it there, a montage with root motion aside, since a dedicated server draws nothing, and server-side i-frames go with it.

**Enemy Character Base** sets **Always Tick Pose and Refresh Bones** on a dedicated server, which also keeps the bones moving, so a socket read outside a melee trace window, such as a projectile's spawn point, sits where the animation puts it. A **SEC Melee Trace Window** keeps the meshes it sweeps refreshing for as long as it runs, so a custom pawn's swings read the animated pose either way.

Clearing **Trigger on Dedicated Server** on the placed notify makes a window client-only, which drops server-side i-frames.

</details>

<details>
<summary>Overlapping windows and restarts (Advanced)</summary>

Unreal treats one notify object on one mesh as a single window. Play a montage twice on the same mesh while the first copy blends out and you get one begin and one end, not a double count. A window that begins again with no end between, as a jump to an earlier section can do, releases the earlier record before re-adding.

Ending a window twice removes its tags once, and a duplicate end leaves a tag held by another system untouched. A window also survives a mid-window change to the owner's resolved ability system, since the tags come off whichever one they went onto.

</details>

<details>
<summary>One montage on several meshes (C++)</summary>

A character can play one montage on more than one mesh, such as first-person arms beside a body, and every notify on that montage then fires once per mesh. The state tag, melee trace, telegraph, gameplay event, anim effect and approach windows ask `SECMontageWindow::IsGameplayMesh` before their gameplay side, so only the mesh it answers true for holds tags, sweeps, announces, sends an event, plays an effect or steers, and the copies stay visual. It answers true for every mesh until a rule is set: call `SECMontageWindow::SetGameplayMeshRule` once at startup with a function that names the mesh that counts, and pass an unbound function to clear it.

</details>

---

Previous page: [Vitals](https://rigbak.com/docs/soulslike-combat/vitals). Next page: [Configuration Reference](https://rigbak.com/docs/soulslike-combat/configuration)
