# Interaction Payloads

> An interaction option's Payload is what the character does when it runs: walk up to the chest, play the opening, and tell the chest the frame the lid lifts. A dodge can break out of it.

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

## Set it up (10 minutes)

1. **Make the chest**

   Create a Blueprint Actor `BP_Chest` with a collision mesh, and tick **Replicates**. Add an **Arrow** where the character should stand, pointing at the chest, with `OpenSpot` in its **Component Tags**, then **UPC Interactable**.

   Components panel of **BP_Chest**:

   - Static Mesh (add)
   - Arrow (add)
   - UPC Interactable (add)

   *The arrow marks the spot and its facing.*
2. **Add the Open option**

   Add an **Options** element: **Option Id** `Open`, **Verb** `Open`, **Name** `Chest`. Set **Payload** to **Play Montage** with the demo's `AM_UPC_ChestOpen`, which already carries the [commit notify](https://rigbak.com/docs/universal-player-combat/interaction-payloads#the-moment-it-lands) on the frame the hands lift the lid, and **Approach**, **Spot Component Tag** to `OpenSpot`.

   **Details panel: UPC Interactable** (component, in BP_Chest)

   **Category: UPC > Interactable**

   | Property | Value |
   | --- | --- |
   | Options | 1 Array element |
   | Options > Index [0] > Option Id | Open |
   | Options > Index [0] > Activation Input Tag | UPC.Input.Interact |
   | Options > Index [0] > Prompt > Verb | Open |
   | Options > Index [0] > Prompt > Name | Chest |
   | Options > Index [0] > Prompt > Icon | None |
   | Options > Index [0] > Payload (Optional) | Play Montage |
   | Options > Index [0] > Payload (Optional) > Montage | AM_UPC_ChestOpen |
   | Options > Index [0] > Payload (Optional) > Play Rate | 1.0 |
   | Options > Index [0] > Payload (Optional) > Section Name | None |
   | Options > Index [0] > Approach > Spot Component Tag | OpenSpot |
   | Options > Index [0] > Approach > Acceptance Radius | 0.0 |
   | Options > Index [0] > Approach > Override Timeout | false |
   | Options > Index [0] > Restrictions |  |
   | Options > Index [0] > Cancel by Ability | true |
   | Options > Index [0] > Priority | 0 |
   | Enabled | true |
   | Anchor Component Tag | None |
   | Anchor Socket | None |

   *The character walks onto the component tagged OpenSpot, plays the montage, and the chest hears On Option Interacted at the montage's commit notify.*
3. **Open the lid when it lands**

   Add a Boolean `IsOpen` set to **RepNotify**. Set it true from **On Option Interacted** (server) and swing the lid in `OnRep_IsOpen` so every player sees it.
4. **Press Play**

   Press **E** beside the chest: the character walks onto the arrow, turns, plays the opening, and the lid swings as the hands lift it.

---

## Pick a payload kind

| Kind | Does, and lands |
| --- | --- |
| (empty) | Nothing on the character; lands at once. |
| **Play Montage** | Plays **Montage** at **Play Rate** from **Section Name**; lands at its [commit notify](https://rigbak.com/docs/universal-player-combat/interaction-payloads#the-moment-it-lands), else as it blends out. |
| **Delay** | Waits **Delay Seconds** (0.5), for a search with no animation. |
| **Trigger Ability / Event** | Sends a gameplay event to the character, or activates its abilities carrying **Ability Tags**; lands straight after. |
| **Run Ability** | Hands the option to [an ability of the character's](https://rigbak.com/docs/universal-player-combat/interaction-payloads#hand-the-option-to-an-ability): no walk, no restrictions, no **On Option Interacted**. |
| **Payload Asset** | Runs [an Action Payload asset](https://rigbak.com/docs/universal-player-combat/interaction-payloads#a-payload-of-your-own), a reusable Blueprint object; lands at a commit notify, else when it finishes. |
| **World Item Pickup** | The reach every world item's Pick Up row carries ([Pickups, Drops and Holders](https://rigbak.com/docs/universal-player-combat/pickups-drops-holders)); lands as the hand closes. |

The Interactor skips a row missing what its kind needs; the actor's other rows still show. Every kind but empty and Run Ability plays through the Interactor's [Payload Ability Class](https://rigbak.com/docs/universal-player-combat/interaction#the-interact-button), which the interaction module grants on its own.

---

## The moment it lands

An option **commits** on the frame it takes effect. Mark it with a **UPC Gameplay Event** notify whose **Event Tag** is `UPC.Event.Interaction.Commit`: the actor's **On Option Interacted** fires once, on the server, and the Interactor fires **On Interaction Committed**.

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

- **Notifies**: UPC Gameplay Event: UPC.Event.Interaction.Commit (at 0.95 s)
- **Chest**: hands reach the lid (0 s to 0.95 s); lid opens (On Option Interacted) (0.95 s to 1.75 s)

*A montage of your own; the times are an example.*

An option cut short before its commit runs nothing, and the actor hears **On Option Cancelled**. A cut after the commit changes nothing: On Option Interacted has run and On Option Cancelled does not follow.

---

## Walk onto a spot first

Name a tagged scene component in the option's **Approach**, **Spot Component Tag**: the character walks onto it at its own speed, turns the way it points, then plays the payload.

**Details panel: UPC Interactable** (component, in BP_Chest)

**Category: Options [0]**

| Property | Value |
| --- | --- |
| Approach > Spot Component Tag | OpenSpot |
| Approach > Acceptance Radius | 0.0 |
| Approach > Override Timeout | false |
| Approach > Advanced > Mode | Move and Face |
| Restrictions > Lock Movement | true |
| Restrictions > Lock Facing | true |
| Restrictions > Lock Camera | false |
| Restrictions > End Running Action | true |

*The defaults: walk onto the spot and turn to its facing, then hold movement and facing and end any running attack for as long as the interaction runs. The camera stays free.*

| Setting | Does |
| --- | --- |
| **Spot Component Tag** | The component to stand on; empty plays where the character stands. |
| **Acceptance Radius** | How close counts as arrived; 0 uses the Interactor's **Approach Acceptance Radius** (5 cm). |
| **Override Timeout**, **Timeout** | This option's patience, in place of the Interactor's **Approach Timeout** (0, no limit). |
| **Mode** (Advanced) | **Move and Face**, **Face Only** (turn in place, for a lever) or **Move Only**. |

The Interactor's **Approach Acceptance Angle** (5 degrees; Move Only ignores it) and **Approach Stall Seconds** (2, ending a walk into a wall) apply too. Giving up cancels with **Could Not Reach**. The walk uses the character's **UPC Attack Approach** and **Character Movement** components, both on the character base.

---

## What the character gives up while it runs

**Restrictions** hold from the moment the server confirms the option until it ends, the walk included.

| Setting | Default | Does |
| --- | --- | --- |
| **End Running Action** | On | Ends the swing playing as the option starts. Off, that swing finishes. |
| **Lock Movement** | On | Stops the player walking it. |
| **Lock Facing** | On | Keeps the facing the walk left. Needs **UPC Attack Approach**. |
| **Lock Camera** | Off | Stops the player turning the camera. |

The character also holds `UPC.State.Interacting` and `UPC.State.ActionsBlocked` while the option runs, which drops combat presses.

---

## Let a dodge break out

The dodge has to be a gameplay ability granted on its own key ([Input](https://rigbak.com/docs/universal-player-combat/input#abilities-that-answer-a-key)), since `UPC.State.ActionsBlocked` shuts the action graph, dodge move included. The demo's `GA_UPC_Dash` (`Demo/Abilities`) is set up this way; no demo ability set grants it. Three edits:

1. **The ability.** In its Class Defaults, add `UPC.Ability.Interaction` to **Cancel Abilities with Tag** (what it ends as it starts) and keep `UPC.State.ActionsBlocked` out of **Activation Blocked Tags** (what stops it starting).
2. **The ability set.** Add a row to the character's ability set naming `GA_UPC_Dash`, with the dodge's Input Tag and Input Action.
3. **The action graph.** The graph answers a key before a granted ability, so delete its transition on the dodge's Input Tag (or give the ability another tag), or the graph's dodge takes the press.

**Cancel by Ability** on the option, on by default, allows the break. Off, the option also ignores **Cancel All Abilities**, such as a call a game makes on death.

Undo a half-done job in **On Option Cancelled**. Its **Reason**:

| Reason | When |
| --- | --- |
| **Cancelled By Ability** | A dodge, stagger or hit reaction took over. |
| **Approach Superseded** | Something else steered the character before it arrived. |
| **Interrupted** | The animation stopped, or the action ended early. |
| **Lost** | The character or actor went away, the actor stopped allowing the option, or the ability left. |
| **Could Not Reach** | The walk gave up. |

---

## Answer per character

A door the character pulls from one side and pushes from the other implements the **UPC Interaction Option Provider** interface (Class Settings, Interfaces). Each function gets the option's own setting as **Authored** and returns **true** with a replacement, or **false** to keep Authored; a function you leave unimplemented returns false.

| Function | The door answers |
| --- | --- |
| **Get Interaction Approach** | Return **true** and Authored copied with **Spot Component Tag** set to the near side's tag, so Acceptance Radius and Mode stay as authored. |
| **Get Interaction Payload** | A Play Montage of the pull or the push. **Payload** holds any payload kind, so wrap it: **Make Play Montage** into **Make Instanced Struct**, into **Payload**. |
| **Get Interaction Restrictions** | What this character may still do. |

They run once as the option starts, so a trace is fine, and cannot change actor variables; the option's events carry the answered row.

An answer must run through the same ability as the authored row's kind, or the authored row plays and a warning logs:

| Authored row | Answers it accepts |
| --- | --- |
| Any kind but empty and Run Ability | Any of those kinds (a pull montage answered with a push montage) |
| **Run Ability** | A Run Ability naming the same ability |
| Empty | Empty |

---

## A payload of your own

1. Make a Blueprint Class of `UPCActionPayload` named `BP_SearchShelf` and override **Execute**. Its **Host** pin is the ability running the payload: drag off it for **Play Montage**, **Play Delay** or **Get Payload Target Actor** (the actor). Return what Play Montage or Play Delay returns: true keeps the run going until that montage or wait ends, and the end lands the option. False ends the run and lands it at once.
2. Right-click in the Content Browser, **UPC**, **Actions**, **Action Payload**, pick `BP_SearchShelf` and name it `PA_SearchShelf`.
3. Set the option's **Payload** to **Payload Asset** with that asset.

Blueprint graph, nodes in reading order:

- **Comment box: BP_SearchShelf · Execute: search for 2 seconds, then the option lands**

  - **Execute** (event); outputs: Host
  - **Play Delay** (function); inputs: Target, Seconds = 2.0; outputs: Return Value
  - **Return Node** (function); inputs: Return Value

**Details panel: UPC Interactable** (component, in BP_MyInteractable)

**Category: Options [0]**

| Property | Value |
| --- | --- |
| Payload (Optional) | Payload Asset |
| Payload (Optional) > Payload | PA_SearchShelf |

*Runs an Action Payload asset from the Content Browser, such as a Blueprint payload of your own.*

Every option using the asset shares that one object, so keep no per-run state in its variables.

---

## Hand the option to an ability

**Run Ability** passes the option to an ability the character has.

**Details panel: UPC Interactable** (component, in BP_MyInteractable)

**Category: Options [0]**

| Property | Value |
| --- | --- |
| Payload (Optional) | Run Ability |
| Payload (Optional) > Ability | None |
| Payload (Optional) > Event Tag | None |

*The named ability takes the option from here.*

1. Grant the ability once, in the character's ability set ([Input](https://rigbak.com/docs/universal-player-combat/input#abilities-that-answer-a-key)).
2. In its Class Defaults, set **Net Execution Policy** to **Server Initiated** or **Server Only**; any other makes the row invalid. Set **Net Security Policy** to **Server Only**, or Data Validation warns.
3. Implement **Activate Ability From Event**. The plugin starts the ability itself with **Event Tag** (`UPC.Event.Interaction` when empty), so it needs no trigger of its own; the event's **Target** is the actor, and **Get Interaction Option Id** on the event's **Target Data** names the option the player chose.

---

## Debug it

`Log LogUPCInteraction Verbose` says why a walk gave up or an actor refused its commit; [Interaction](https://rigbak.com/docs/universal-player-combat/interaction#debug-it) covers the overlay.

<details>
<summary>How a run goes (Advanced)</summary>

The server confirms the option. A cancel at any stop skips to the end.

1. **Take what the option asks for** (Restrictions): A running attack ends (End Running Action), and walking, facing and the camera are held as the Restrictions say. The character reports On Interaction Started.
2. **Walk onto the spot** (Approach): With a Spot Component Tag, the character walks onto that component at its own speed and turns to its facing. Without one, the payload runs where the character stands.
3. **Check again on arrival** (Can Interact on the interactable): After a walk, the interactable is asked Can Interact once more, and the server checks the character is still in reach. A no cancels the run with Lost. With no walk, this step is skipped.
4. **Play the payload** (Play Montage, Delay, Trigger Ability / Event, Payload Asset): The montage plays, the delay runs, the event is sent or the payload asset runs, on the server and on the player's own machine.
5. **Commit** (a UPC Gameplay Event notify on UPC.Event.Interaction.Commit, or the payload's end): The interactable hears On Option Interacted, once, on the server. The character reports On Interaction Committed. A montage with no commit notify commits as it starts blending out.
6. **End** (On Interaction Ended, On Option Cancelled): The holds come off and the character reports On Interaction Ended. A run that ended before its commit tells the interactable On Option Cancelled with the reason instead.

A dodge naming UPC.Ability.Interaction in Cancel Abilities with Tag, a montage that is stopped, or a walk that gives up all end the run early; before the commit, nothing commits.

- On arrival, **Can Interact** runs again and the server checks reach: within Detection Radius of the actor, or on the spot, plus the arrival radius and 0.3 s of walking. A no cancels with Lost; Face Only skips it.
- A character another approach steers, such as an attack glide, cancels with Approach Superseded.
- An actor destroyed before the commit cancels with Lost; after it, the run lands.
- **Lock Movement** and **Lock Camera** reach a possessed character only.
- A payload ability whose Asset Tags lose `UPC.Ability.Interaction` warns, since no dodge can then break its interactions.

</details>

<details>
<summary>The demo</summary>

`BP_UPC_Chest` (Open, Break) and `BP_UPC_Door` (Open, Kick) set a replicated variable on the server and play it in its RepNotify. `BP_UPC_Door` answers all three per-character functions, from the side the character stands on.

</details>

<details>
<summary>What runs where (Multiplayer)</summary>

Only the server starts, abandons or commits a payload, and its end is final. The player's machine plays the walk and montage from its own copy of the actor, with no payload sent.

- The player's own movement walks the character, so the walk is predicted; a client copy that loses its option or montage ends alone.
- Per-character answers run on each machine, so read shared state such as positions; in a door's hinge plane the machines can pick different sides.
- A dodge the server refuses, after the player's machine cancelled, leaves the player cancelled while the server commits.
- The server judges a remote player's arrival on each move, and accepts one at rest after walking toward the spot within the widened reach.

</details>

<details>
<summary>C++</summary>

- A payload kind derives from `FUPCInteractionPayloadSpec` (a `USTRUCT` with a `DisplayName`), overriding `IsDefinitionValid`, `ResolveExecutionAbilityClass`, `GetExecutionTriggerTag`, `CanStart` and `BuildPayload`. Build it with `InitializeAs<FYourSpec>()`; `TInstancedStruct::Make` given a derived value keeps only the base.
- A native payload derives from `UUPCActionPayload`, overriding `Execute(UUPCPayloadHostAbility& Host)` and optionally `CanStart` and `CollectPreloadAssets`; `GetActionGraph()` is null in an interaction.
- `IUPCInteractionOptionProvider` uses `GetInteractionApproach_Implementation`, `GetInteractionRestrictions_Implementation` and `GetInteractionPayload_Implementation` (an `FInstancedStruct` holding an `FUPCInteractionPayloadSpec`). `UUPCInteractionPayloadAbility::GetInteractable` and `GetOption` read the running option.
- A Run Ability's event carries the Option Id in its target data: `UUPCInteractionStatics::GetInteractionOptionId(EventData.TargetData)` reads it, and `FGameplayAbilityTargetData_UPCInteraction::Find(EventData.TargetData)` returns the actor and `OptionId`.

</details>

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

| Log | Fix |
| --- | --- |
| "... built nothing to run" | Fill in the payload. |
| "... names approach spot tag '...', but no scene component on the actor carries it" | Tag the component, or clear the field. |
| "... has no Character Movement component to walk with" | Add one, or set Mode to Face Only. |
| "... has no Attack Approach component to hold it" | Add **UPC Attack Approach**. |

</details>

---

Previous page: [Interaction](https://rigbak.com/docs/universal-player-combat/interaction). Next page: [Paired Actions](https://rigbak.com/docs/universal-player-combat/paired-actions)
