# Melee Trace

> Melee trace lands a weapon's hits: the item names its hit volumes, a window on the attack montage opens them, and a sweep fills the gap between frames, so a fast swing connects at 30 FPS and at 144.

Markdown version of https://rigbak.com/docs/universal-player-combat/melee-trace, a page of the Universal Player Combat documentation. Link that page when citing it.

This page continues [First Combo](https://rigbak.com/docs/universal-player-combat/first-combo): `Item_MySword` is the item you made there.

## Set it up (3 minutes)

1. **Give the item a hit volume**

   Open `Item_MySword`, expand its **Equippable** fragment and find the row in **Trace Sockets**. An item with a **Visuals** mesh and no actor class shows that mesh on a component tagged `UPC.ItemMesh`, so the row names that tag.

   In **Item_MySword**, under Equippable > Trace Sockets > Index [ 0 ], set:

   | Property | Value |
   | --- | --- |
   | ID | Blade (replaces None) |
   | Source Component Tag | UPC.ItemMesh (replaces None) |
   | Shape | Capsule Two Point (replaces Sphere) |

   *Socket or Bone Name and End Socket or Bone Name start on TraceStart and TraceEnd. Add sockets by those names to the weapon mesh, hilt to tip, or name sockets it has.*

   The UPC Character Base carries the **UPC Melee Trace** component the row registers on. On a pawn of your own, add that component and send the ready signal as [Character Setup](https://rigbak.com/docs/universal-player-combat/character-setup) shows.
2. **Create a damage config**

   Create the asset: right-click in the Content Browser, choose **UPC > Damage and Defense > Damage Config**, and name it **Damage_MySword**.

   *Right-click in the Content Browser, UPC, Damage and Defense, Damage Config.*

   Set **Damage** and add `UPC.DamageType.Slash` to **Damage Tags**. [Damage and Hit Effects](https://rigbak.com/docs/universal-player-combat/damage-and-hit-effects) covers the rest of the asset.
3. **Point the trace windows at it**

   Open `AM_UPC_Sword_Combo`. Each swing has a **UPC Melee Trace Window** with **Socket IDs** `Blade`; set **Damage Config** on each to `Damage_MySword` in place of the demo's `Damage_UPC_Sword`. The demo sword plays this montage too; to keep the demo as it ships, duplicate the montage and point your graph's nodes at the copy. On a montage of your own, add the Notify State **UPC Melee Trace Window** across the strike frames and set both fields.

   **Timeline: AM_UPC_Sword_Combo** (2 s long). Tracks:

   - **Notifies**: Melee Trace: Blade (0.3749 s to 0.5271 s); Melee Trace: Blade (0.8377 s to 1.087 s); Melee Trace: Blade (1.3464 s to 1.658 s)

   *Each window covers the frames where the blade can hurt.*
4. **Play, and watch the sweep**

   Press Play, draw the sword and run `UPC.Debug.Melee.DrawTracing 1`. The swept shape draws while the window is open and changes color on a hit. The item's sockets exist only while it is drawn. A target needs collision that blocks the **Pawn** channel, the default **Trace Filter**; the demo dummies have it.

---

## Shape the sweep

*Interactive diagram on the page: Without Interpolation: The fast sword swings 'teleport' over the target between frames, causing a miss.*

| Shape | Pick it for |
| --- | --- |
| **Sphere** | A fist, a pommel, a small contact point. **Radius** (15 cm) is the whole setup. |
| **Capsule** | A wider path for one contact point. It lies along the way the socket moved, so **Capsule Half Height** lengthens the sweep, not the weapon. |
| **Capsule Two Point** | A blade from hilt to tip, spanning **Socket or Bone Name** to **End Socket or Bone Name**. |

Give each contact point a row and an **ID** of its own, so a blade and a pommel can trace in different windows.

---

## Hit volumes from items

**Details panel: Trace Socket** (data asset, in Item_MySword > Equippable)

**Category: Trace**

| Property | Value |
| --- | --- |
| ID | Blade |
| Source Component Tag | UPC.ItemMesh |
| Shape | Capsule Two Point |
| Socket or Bone Name | TraceStart |
| End Socket or Bone Name | TraceEnd |
| Radius | 15 |

**Category: Debug**

| Property | Value |
| --- | --- |
| Debug Color | R 1, G 0, B 0, A 1 (sRGB) |

*One row of the Equippable fragment's Trace Sockets. Drawing the item registers it on the character's UPC Melee Trace; putting it away takes it off.*

A row registers on the character's **UPC Melee Trace** as the item is drawn and comes off as it is put away. **Source Component Tag** picks the mesh it rides:

- **Empty**: the character's own body mesh. Bare hands work this way: the demo's unarmed item, `Item_UPC_Unarmed`, names the bone `hand_r`.
- **A tag**: the component carrying it on the item's actor, else on the character and what is attached to it. A weapon Blueprint with a blade mesh tags that mesh component `Blade.Mesh` and the row names `Blade.Mesh`.

A character that never holds an item registers its sockets from Blueprint instead ([Fists, claws and anything without a weapon](https://rigbak.com/docs/universal-player-combat/melee-trace#fists-claws-and-anything-without-a-weapon)).

**Hold Places**, on the same Equippable fragment, lists where the item can be held, in order of preference ([Equipment](https://rigbak.com/docs/universal-player-combat/equipment#where-an-item-is-held-hold-places)). Held in the first place, a row registers under its own **ID**. Held in another, the ID gains that place's name: in `UPC.Place.Main` the row is `Blade`, in `UPC.Place.Off` it is `Blade_Off`, which a window naming `Blade` does not sweep.

---

## The montage window

**Details panel: UPC Melee Trace Window** (anim notify, in AM_MySword_Attack)

**Category: Melee Trace**

| Property | Value |
| --- | --- |
| Socket IDs | 1 Array element |
| Socket IDs > Index [0] | Blade |
| Damage Config | Damage_MySword |
| Extra Damage Tags | no tags |

**Category: Debug**

| Property | Value |
| --- | --- |
| Enable Debug Draw | false |

*Notify state over the strike frames. Empty Socket IDs sweeps every registered socket.*

- **Socket IDs** empty sweeps every socket the character has registered; each name you add must match a socket **ID** exactly.
- **Extra Damage Tags** describe this swing on top of its damage config's tags, so one config serves a combo whose windows differ: three slashes marked counterable, a finisher marked unblockable.
- One trace runs one window at a time; a window opening over another closes the first and logs it.

---

## How often a swing lands

| Setting on UPC Melee Trace | Does |
| --- | --- |
| **Hit Reset Interval** (0) | Seconds before one target can take another hit in the same window. 0 lands once per target; 0.15 suits a spin or a drill. |
| **Max Targets Per Swing** (0) | Targets one swing cuts through: 0 is everyone, 1 a stab that cannot clip the enemy behind. Only damageable targets count, a blocking one included. Tick **Scenery Counts Toward Swing Limit** to count walls too. |
| **Skip Record Tags** (empty) | Result tags a defense reports, such as `UPC.DamageResult.Blocked` ([Defense](https://rigbak.com/docs/universal-player-combat/defense#tell-the-attacker-what-happened)), that leave the swing unspent on that target. Empty spends the swing on a target whatever it reported; with **Blocked** listed, a blocked swing stays live on it. |

An attack with its own repeat timing or target count sets **Multi Hit Interval** and **Max Targets Per Swing Override** on its damage config; `-1` keeps the component's values.

---

## Who a swing can hit

**Details panel: UPC Melee Trace** (component, in UPC Character Base (MeleeTrace))

**Category: Damage**

| Property | Value |
| --- | --- |
| Team Filter | Enemies Only |

*Starts on Enemies Only, so a swing spares teammates. Filters who a swing can damage, separate from targeting.*

**Team Filter** starts on **Enemies Only**: a swing spares teammates and hits anyone hostile or on no team. **No Filter** allows friendly fire, **Friendlies Only** suits a healing weapon, and **Neutral Only** hits actors on no team and those the attacker's team excludes. Teams come from the **UPC Team** component on the pawn.

| You want | Set |
| --- | --- |
| A dodge the swing passes through | Hold `UPC.State.Intangible` over the dodge ([Animation Integration](https://rigbak.com/docs/universal-player-combat/animation-integration)). **Pass Through Tags** lists it: the swing lands nothing on that target and carries on behind it. |
| A mount or a companion the swing ignores | **Add Trace Ignored Actor**. The sweep already skips the wielder and everything attached to it. |
| A swing that reaches a ragdoll ignoring the Pawn channel | **Trace Filter** on **Object Types**. Nothing stops that sweep, walls included, so keep **Channel** wherever the level should shield a target. |

<details>
<summary>React to every landed hit (Advanced)</summary>

Each landed hit passes through the trace's **Confirmed Hit Ability Class** before it deals damage; the UPC Character Base grants it on its own. To add logic to each hit, such as a combo counter:

1. Make a Blueprint child of **UPC Confirmed Hit Ability**.
2. Override **On Hits Confirmed** and call the parent, so the hits still deal damage.
3. Set the child as **Confirmed Hit Ability Class** on the character's **UPC Melee Trace**.

The character receives the class as its ability system comes up (**Notify Ability System Ready**), unless it already holds that class or a child of it, as a starting ability set can grant. Grant one only: a second deals each hit again, and the trace warns. With none granted, the sweep deals each hit itself in single player and on the server, and a client player's hits are lost.

</details>

---

## Debug it

```
UPC.Debug.Melee.DrawTracing 1   // Every sweep, in its socket's Debug Color, changing color on a hit
```

**Draw Debug** on one trace, or **Enable Debug Draw** on one window, draws that one alone; **Debug Draw Duration** (0.1 s) is how long a shape stays. The Output Log names a socket a window asked for that nothing registered, a window opened over another, an **Object Types** filter with no types, a sensor collider blocking the sweep, and an item drawn onto a character with no **UPC Melee Trace**.

<details>
<summary>What a swing lands on (Advanced)</summary>

Each contact sorts into one kind:

| Kind | What it is | Damage | The swing |
| --- | --- | --- | --- |
| **Damageable** | A live target, one a **UPC Invulnerable** response protects included. | Sent | Spent on it |
| **Inert** | A combatant taking nothing now, such as a pawn with Can be Damaged off. | None | Spent, and reachable again once it takes hits |
| **Scenery** | A wall, a floor, a prop. | None | Held for the window, so a wall costs one clang |

- **Respect Can be Damaged** (on) makes a target with Can be Damaged off inert, so switching it off on death quiets a corpse.
- **Require Damageable Target** sends no damage to anything without **UPC Damageable** (a pawn sorts as inert, anything else as scenery). Leave it off while a breakable crate takes hits through Any Damage.
- A swing passes through a trigger box: a component with no physics collision that lets pawns through, on an actor that is neither a pawn nor **UPC Damageable**. An overlap-only hit box on a character still takes the blow.

</details>

<details>
<summary>Colliders the swing reports instead of hitting (Advanced)</summary>

For a parry box or a wake-up volume: tag the collider, list the tag under **Sense Component Tags**, and set its response to the trace channel to **Overlap**. A swing crossing it fires **On Melee Sensed** once per window, spends nothing and reaches the body behind in the same frame. On **Block** the sweep stops at the sensor.

</details>

<details>
<summary>Fists, claws and anything without a weapon (Alternative)</summary>

A pawn with no item registers its own sockets from Blueprint, usually on Begin Play, and names them on the window as a weapon's are:

**Register Sphere Socket** registers one point on a bone (a hand, a foot, a horn), **Register Capsule Socket** one point with a wider swept path, **Register Two-Point Capsule** a span between two bones or sockets.

A socket registered under an ID in use replaces it; **Unregister Trace Socket** and **Unregister All Sockets** remove them. A weapon Blueprint can add sockets from **On Drawn** and remove them in **On Stowed**, under IDs its **Trace Sockets** rows do not use.

</details>

<details>
<summary>Opening a trace window without a montage notify (Alternative)</summary>

| Node | Does |
| --- | --- |
| **Start Tracing** | Opens a window on the socket IDs given, every socket when empty, with a damage config and a debug draw override. |
| **Start Tracing Simple** | The same with a damage figure in place of a config; below zero uses **Base Damage**. With no config it runs no hit effects and sends **Damage Type Class**. |
| **Start Tracing with Tags**, **Start Tracing Simple with Tags** | The same two, with **Extra Damage Tags** for this swing. |
| **Stop Tracing** | Closes the window and clears its hit records. |

**Get Registered Socket IDs** lists the sockets, and **Is Tracing** answers whether a window is open.

</details>

<details>
<summary>Changing one phase of the pipeline (Advanced)</summary>

Override one phase's event on a Blueprint child of **UPC Melee Trace**. A character built on the UPC Character Base takes the child through a C++ subclass naming it for the **MeleeTrace** component; your own character carries it in place of **UPC Melee Trace**.

| Event | Controls |
| --- | --- |
| **Build Damage Info** | The damage before the trace sends it, for crits or an elemental pass. It receives the socket that struck. |
| **Handle Damage Result** | Whether the trace records a hit. The default records all but a result in **Skip Record Tags**; an override calls **Record Hit** for each hit it keeps. |
| **Classify Hit** | The Damageable, Inert or Scenery sorting. |
| **Classify Contact** | Body to damage, sensor to report, or nothing. Call **Is Pass Through Target** and **Is Trigger Contact** to keep the default rules. |
| **Should Detect Hits** | Which machine sweeps, by default the one **Hit Detection Authority** names. |

**Can Hit Actor**, **Record Hit** and **Get Targets Hit This Window** (for damage falling off across a cleave) support the overrides. A child of **UPC Damage Config** can carry more per attack, such as a stagger tier, for the target to read in **Handle Incoming Damage**.

</details>

<details>
<summary>Which machine finds a hit (Multiplayer)</summary>

**Details panel: Universal Player Combat** (project settings, in Project Settings > Plugins)

**Category: Combat > Multiplayer**

| Property | Value |
| --- | --- |
| Default Hit Detection Authority | Client Authoritative |

**Category: Combat > Hit Stop**

| Property | Value |
| --- | --- |
| Max Hit Stop Seconds | 0.30 |

**Category: Combat > Rewind**

| Property | Value |
| --- | --- |
| Rewind History Seconds | 1.0 |
| Rewind Memory Budget MB | 8.0 |

*Project-wide combat defaults, saved to DefaultGame.ini.*

**Hit Detection Authority** on **UPC Melee Trace** picks the machine that sweeps; **Project Default** reads **Default Hit Detection Authority** in Project Settings, Plugins, Universal Player Combat.

| Setting | Sweeps |
| --- | --- |
| **Client Authoritative** | The default. The controlling player's machine finds that player's hits, so a swing connects on screen the moment it touches; the server finds the hits of characters no player controls. |
| **Server Authoritative** | The server finds every hit and refuses hits a player's machine reports. A player sees contact a round trip late. |

- **On Melee Hit** and **On Melee Sensed** fire on the machine that swept; **On Melee Hit Response** where the hit resolved.
- Put the team on the pawn: a team id on a controller reads as no team on another player's machine.
- A window started by hand reaches the server with no damage config, so its reported hits land there with the trace's **Default Damage Config**.

</details>

<details>
<summary>How the server checks a reported hit (Multiplayer)</summary>

**Details panel: Class Defaults** (Blueprint, in GA_MyConfirmedHit)

**Category: UPC > Confirmed Hit**

| Property | Value |
| --- | --- |
| Hit Validators | 4 Array elements |
| Hit Validators > Index [0] | Melee Trace Window |
| Hit Validators > Index [0] > Grace Seconds | 0.50 |
| Hit Validators > Index [1] | Pass Through |
| Hit Validators > Index [2] | Plausible Hit |
| Hit Validators > Index [2] > Extra Reach | 150 |
| Hit Validators > Index [3] | Rewind Hit |
| Hit Validators > Index [3] > Max Rewind Seconds | 0.50 |
| Hit Validators > Index [3] > Time Tolerance | 0.10 |
| Hit Validators > Index [3] > Distance Tolerance | 30 |
| Untied Hit Spacing | 0.5 |

*A Blueprint child of the ability, set as the melee trace's Confirmed Hit Ability Class. These are the defaults it inherits.*

The confirmed hit ability's **Hit Validators** run on the server over each hit before it deals damage; the first that refuses drops it.

| Check | Refuses a hit when |
| --- | --- |
| **Melee Trace Window** | A player's machine reported it, and the attacker's montage is not playing the window it names, within **Grace Seconds** of its span. |
| **Pass Through** | The target holds one of the attacker's **Pass Through Tags**. |
| **Plausible Hit** | The target is the attacker or something it carries, a teammate its **Team Filter** spares, or farther than its sockets reach plus **Extra Reach** and the movement a round trip explains. |
| **Rewind Hit** | The target carries a **UPC Rewind History** and the impact point lay farther than **Distance Tolerance** from it where the player saw it, about a round trip earlier. |

- Add **UPC Rewind History** to each character a remote player can hit, so the server keeps where it stood. **Rewind History Seconds** (1 second) and **Rewind Memory Budget MB** (8 MB) in Project Settings, Plugins, Universal Player Combat bound the record.
- Every check but Pass Through passes a hit the server swept itself; a check of your own reads **Swept Here** to do the same.
- A hit passing every check lands only as often, and on as many targets, as its window allows. **Untied Hit Spacing** (0.5 s) spaces reported hits that belong to no montage window.

</details>

<details>
<summary>Extending the trace (C++)</summary>

- `UUPCCombatTraceComponent` is **UPC Melee Trace**; its base `UUPCMeleeTraceComponent` is **UPC Melee Trace (Base)**, not offered in Add Component.
- `DeliverHit` carries a swept hit onward, raising `UPC.Event.MeleeHit` for the confirmed hit ability. `KeepsSweepingAfterEnd` keeps a window sweeping past its end while a hit stop holds its pose. `OpenWindow` and `CloseWindow` see every window.
- A hit check subclasses `UUPCHitValidator` and overrides **Validate Hit**, in C++ or Blueprint.
- `UUPCRewindSubsystem` (**UPC Rewind**) answers any hit source, a projectile included, against recorded targets: `Sweep` (**Rewind Sweep**) and `GetClosestDistance`, and the static `GetViewDelay`, how long ago a player saw a target. `RegisterActor` and `RegisterComponent` record without the component.
- `UUPCAbilitySystemReady::NotifyAbilitySystemReady(Avatar, AbilitySystem)` is the **Notify Ability System Ready** node.

</details>

<details>
<summary>Troubleshooting (Advanced)</summary>

**Nothing lands**

| Problem | Fix |
| --- | --- |
| No hits at all | Match **Socket IDs** to a socket **ID**, or clear the list. Check the item is drawn. |
| A client player's swings deal nothing | Nothing confirms the hit there; the trace warns once. On a pawn not built on the base, send the ready signal ([Character Setup](https://rigbak.com/docs/universal-player-combat/character-setup)). |
| A wall plays the flesh cue | A wall with Can be Damaged on and no **UPC Damageable** counts as a live target. Switch the flag off on level geometry, or tick **Require Damageable Target**. |
| Two hits from one swing | **Hit Reset Interval** or the config's **Multi Hit Interval** is above 0. |
| A hit lands but nothing takes damage | Implement **UPC Damageable** on the target, or leave **Damage Application** on **Damageable Interface** so Unreal's point damage runs. |

</details>

Previous page: [Sprint and Speed](https://rigbak.com/docs/universal-player-combat/sprint-and-speed). Next page: [Damage and Hit Effects](https://rigbak.com/docs/universal-player-combat/damage-and-hit-effects)
