# Interaction

> Add UPC Interactable to any actor and a character can use it: pull a lever, open a door. The character's UPC Interactor picks the best one nearby, a prompt shows the key, and a press runs the option.

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

## Set it up (5 minutes)

1. **Make the lever**

   Work in the demo map `LVL_UPC_Demo` ([Getting Started](https://rigbak.com/docs/universal-player-combat/getting-started)): its player, `BP_UPC_Character`, has the Interactor, the E key and the prompt. Create a Blueprint Actor named `BP_Lever` with a collision Static Mesh (the character measures its distance to that collision), then click **Add** and pick **UPC Interactable**.

   Components panel of **BP_Lever**:

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

   *A mesh to stand next to, and the component that makes the actor usable.*
2. **Give it one option**

   Select **UPC Interactable**, add an element to **Options** and set **Option Id** to `Pull`. Under **Prompt**, set **Verb** to `Pull` and **Name** to `Lever`. Leave **Activation Input Tag** on `UPC.Input.Interact` and **Payload** empty.

   In **BP_Lever**, under Options [0], set:

   | Property | Value |
   | --- | --- |
   | Option Id | Pull (replaces None) |
   | Activation Input Tag | UPC.Input.Interact |
   | Prompt |  |
   | Prompt > Verb | Pull |
   | Prompt > Name | Lever |

   *With no payload, the actor's own event runs the moment the player uses the option.*
3. **React when the player pulls it**

   In the Details panel's **Events**, click **+** beside **On Option Interacted** and drag a **Print String** off the new event.

   Blueprint graph, nodes in reading order:

   - **Comment box: BP_Lever · Event Graph**

     - **On Option Interacted (UPCInteractable)** (event); outputs: Instigator, Option
     - **Print String** (function); inputs: In String = Hello
4. **Place it and press Play**

   Drop `BP_Lever` in the level, press Play, walk up and press **E**: the Print String shows. A character of your own needs [an Interactor and the key](https://rigbak.com/docs/universal-player-combat/interaction#the-interact-button).

---

## Options: one row per action

Each row in **Options** is one thing the actor offers: a lever has one, a door might offer Open and Kick.

| Setting | Does |
| --- | --- |
| **Option Id** | The action's name, unique on the actor; **On Option Interacted** hands it back. |
| **Activation Input Tag** | The button that runs it; empty is `UPC.Input.Interact`. |
| **Prompt** | **Verb**, **Name** and an optional **Icon**. |
| **Payload** | What the character plays before the option completes, such as a walk and a montage ([Interaction Payloads](https://rigbak.com/docs/universal-player-combat/interaction-payloads)). |
| **Approach**, **Restrictions**, **Cancel by Ability** | For a payload: where the character stands, what it gives up, whether an ability such as a dodge can break the interaction. |
| **Priority** | The higher wins a tie between two options on one button. |
| **Enabled** | On the component. Off offers nothing; **Set Interaction Enabled** changes it in play, on the server. |
| **Anchor Component Tag**, **Anchor Socket** | On the component. Where a prompt pins; empty is the middle of the actor's bounds. |

**On Option Interacted** fires on the server once the option runs, and **On Option Cancelled** when a payload ends before it lands ([Let a dodge break out](https://rigbak.com/docs/universal-player-combat/interaction-payloads#let-a-dodge-break-out)).

---

## Several actions on one actor

Each option answers one button. Put a second action on `UPC.Input.Interact.Secondary`, a third on `.Tertiary`, a fourth on `.Quaternary`, and grant the interact ability once per tag. **Priority** compares options on one button of one actor; the Interactor picks the actor first ([Detection](https://rigbak.com/docs/universal-player-combat/interaction#choose-how-a-character-finds-things)).

---

## The interact button

The character's **Starting Ability Set** (the abilities it has from the start, in its Class Defaults), or an item's ability set, grants the interact ability once per button ([Input](https://rigbak.com/docs/universal-player-combat/input#abilities-that-answer-a-key)):

| Ability | Input Tag | Input Action |
| --- | --- | --- |
| `UPCInteractAbility` | `UPC.Input.Interact` | Your interact Input Action |
| `UPCInteractAbility`, a row per extra button | `UPC.Input.Interact.Secondary` | That button's Input Action |

The **UPC Interactor** grants the ability that plays payloads itself (its **Payload Ability Class**, `UPC Interaction Payload Ability` by default). UPC Character Base creates the Interactor; a character of your own needs one added, plus the ready signal and input from [Character Setup](https://rigbak.com/docs/universal-player-combat/character-setup).

---

## Choose how a character finds things

**Detection** on the **UPC Interactor** says what wins, **Tracking** when it looks.

Nearest

Nearest: Closest wins, whichever way the character faces.

Closest wins, whichever way the character faces.

Focused

Focused: Inside the view cone beats outside, nearer or not.

Inside the view cone beats outside, nearer or not.

Aim

Aim: Whatever the trace from the view hits.

Whatever the trace from the view hits.

Overlap

Overlap: The one whose trigger the character stands in.

The one whose trigger the character stands in.

*Seen from above: the character in blue facing up, the dashed ring its Detection Radius, the green square the interactable each Detection choice picks.*

| Detection | Picks |
| --- | --- |
| **Nearest** | The closest interactable, whichever way the character faces. |
| **Focused** | The default. One inside **Focus Cone Half Angle** (45 degrees) of the view first, else the closest. |
| **Aim** | What a trace from the view hits, for crosshairs. The actor must block **Aim Trace Channel**; **Aim Trace Radius** (8 cm) catches a thin handle. |
| **Overlap** | Interactables whose trigger volume the character stands in, closest first. Add a **Box Collision** to the actor: its default preset overlaps the character, with nothing to wire. |

| Tracking | Looks |
| --- | --- |
| **Continuous** | The default. Every **Candidate Update Interval** (0.1 s; 0 is every frame), so a prompt shows before the press. |
| **On Demand** | Only on the press, so no prompt. **Refresh Candidate** looks once on request. |

**Details panel: InteractorComponent** (component, in AUPCCharacterBase)

**Category: UPC > Interactor**

| Property | Value |
| --- | --- |
| Detection | Focused |
| Tracking | Continuous |
| Detection Radius | 200 |
| Candidate Update Interval | 0.1 |
| Require Sight | None |
| Required Tags | no tags |
| Blocked Tags | no tags |
| Focus Cone Half Angle | 45 |

**Category: UPC > Interactor > Approach (collapsed until clicked)**

| Property | Value |
| --- | --- |
| Approach Acceptance Radius | 5 |
| Approach Acceptance Angle | 5 |
| Approach Timeout | 0 |
| Approach Stall Seconds | 2 |

**Category: UPC > Interactor > Pickup (collapsed until clicked)**

| Property | Value |
| --- | --- |
| Pickup Presentation |  |

**Category: UPC > Interaction > Debug**

| Property | Value |
| --- | --- |
| Debug Overlay Interaction | false |

*Created by the character base. Focused shows Focus Cone Half Angle; Aim shows Aim Trace Channel and Aim Trace Radius instead; Nearest and Overlap show neither.*

**Detection Radius** (200 cm) caps every mode, measured to the interactable's first collision shape.

---

## Who may interact

- **The character:** it needs every **Required Tag** on its Interactor and none of the **Blocked Tags** (a stagger, a cutscene), or the Interactor offers it nothing.
- **The actor:** turn **Enabled** off, or override **Can Interact** in a Blueprint child of **UPC Interactable**: a key in the bag, a quest step done.
- **One row:** override **Get Interaction Options** there to hand this character its own rows. The prompt shows what it answers, and it is asked again once the option starts. Two cases:

  - **Relabel:** return the authored `Open` row with its Verb set to `Unlock`. **On Option Interacted** fires with `Open` as usual.
  - **A new action:** return a row with a new Option Id such as `Unlock`, and override **Execute Interaction Option** to run it; without that, the row shows and does nothing.
- **Approach, payload or restrictions:** to change how a character performs an option, not which rows it sees, use [per-character answers](https://rigbak.com/docs/universal-player-combat/interaction-payloads#answer-per-character).
- **Sight:** **Require Sight** on the Interactor refuses what the character cannot see. **From Socket** looks from the **Sight Socket**, a hand or the head; **From View** looks from that socket and from the camera, and refuses what either cannot see. A wall hides what it blocks on **Sight Channel** (Visibility).

---

## Show a prompt

The demo's prompt is `WBP_UPC_Interactions` (`Demo/UI/Widgets/Interactions`), a `WBP_UPC_Interaction` row per button. For your own, bind these on the player's UPC Interactor:

| Use | To |
| --- | --- |
| **On Candidate Changed** | Highlight the new candidate, clear the old; either pin can be empty. |
| **On Available Interaction Options Changed**, **Get Available Interaction Options** | Rebuild the rows, one per button, each with its **Prompt** and **Activation Input Tag**. |
| **Get Current Interaction Point** | The world point to pin the prompt to; project it each frame. |
| **On Interacting Changed** | Hide the prompt while the character is busy, its walk to a spot included. |

A row can show and refuse a press, as a [pickup with no room](https://rigbak.com/docs/universal-player-combat/pickups-drops-holders#when-there-is-no-room) does. For a locked door, set two fields in **Get Interaction Options**: **Disabled Reason**, a tag of your own such as `Door.Locked` that marks the row refused so your prompt can gray it, and the **Prompt** **Verb** `Locked`. Key art comes from the [input prompt widgets](https://rigbak.com/docs/universal-player-combat/hud-and-input-prompts#show-the-key-for-an-input).

---

## Debug it

`UPC.Debug.Interaction 1` writes above each character its Detection, Tracking, the actor in focus and the option a press would run, or "Nothing in reach" and "No option offered"; **Debug Overlay Interaction** on one Interactor does it for that character. `Log LogUPCInteraction Verbose` says why each candidate or option was passed over.

<details>
<summary>How the Interactor picks (Advanced)</summary>

- It looks only on the machine controlling the character, after the camera moves each frame. It checks Required and Blocked Tags (a Blocked Tag wins), walks the ranked candidates, checks sight, builds one winner per button, and stops at the first actor offering a usable row.
- **Nearest** and **Focused** break a tie by actor name; **Focused** reads the controller's camera, else the character's eyes. **Aim** sweeps as far as the view's distance to the character plus Detection Radius, ignoring the character and what it carries; a hit on an attached part counts for its actor.
- On one button a usable row beats a disabled one, then the higher Priority, then the Option Id that sorts first.
- The Interactor reads several UPC Interactable components on one actor together, and skips an Option Id after its first use.
- A tag arriving mid-interaction does not end it; [a dodge does](https://rigbak.com/docs/universal-player-combat/interaction-payloads#let-a-dodge-break-out). Attached actors, such as items on a rack, do not block sight to it.
- **Get Current Selection** gives the row on `UPC.Input.Interact`, else the first; **Get Interaction Option for Input** one button's row.
- **Set Detection** and **Set Tracking** switch the modes in play.

</details>

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

`BP_UPC_Character` uses **Nearest** detection and **Require Sight** on **From View**. `AbilitySet_UPC_Default` grants `UPCInteractAbility` on `UPC.Input.Interact` (`IA_UPC_Interact`, E) and `.Secondary` (`IA_UPC_InteractSecondary`, F). `BP_UPC_Door` (Open, Kick) and `BP_UPC_Chest` (Open, Break) put two buttons on one actor.

</details>

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

The player's machine picks the candidate and shows the prompt. A press sends the actor and the Option Id, and the server checks again:

A press arrives on the server. The first check that fails refuses the press.

1. **Reach** (Detection Radius on the UPC Interactor, plus Server Range Tolerance): The chosen actor's collision has to be within Detection Radius of the character, plus 25 cm for movement and network delay. The server never swaps the chosen actor for another one.
2. **Tags and sight** (Required Tags, Blocked Tags and Require Sight on the UPC Interactor): The character must carry every Required Tag and no Blocked Tag, and see the actor when Require Sight asks for it.
3. **The actor still offers the option** (Can Interact and Get Interaction Options on the UPC Interactable): The actor's components are asked again for this character. The option has to be offered: a row with a broken definition drops out alone and the actor's other options stay. A row with a Disabled Reason shows on the prompt and runs nothing.
4. **The input** (the option's Activation Input Tag): The option has to answer the input the press came through. The server reads that input from the ability the player activated, never from the player's message.
5. **It runs** (Payload (Optional)): An option with no payload fires On Option Interacted at once. Any other option starts its ability on the character, which needs one grant of that ability or a child of it.

The player's own machine runs the same tag, sight and option checks before it shows a prompt, so a refusal here needs the world to have changed in between.

- **On Option Interacted** fires on the server: show its result through a RepNotify variable on an actor with **Replicates** ticked, which also carries **Enabled** to the prompts.
- **Can Interact** and **Get Interaction Options** run on both machines; the server's answer decides, and a row it finds disabled runs nothing.
- A machine deciding for another player checks **From View** by the socket line alone.
- The interact ability's Advanced Class Defaults: **Server Range Tolerance** (25 cm) past Detection Radius, and **Server Selection Timeout** (2 s) for a remote player's choice.

</details>

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

- `UUPCInteractableComponent` is `Blueprintable`; override `CanInteract_Implementation`, `GetInteractionOptions_Implementation`, `ExecuteInteractionOption_Implementation` (returns `FUPCInteractionResult`), `OnInteractionCancelled_Implementation` and `GetInteractionPoint_Implementation`. `UUPCWorldItemInteractableComponent` routes `PickUp` to `AUPCWorldItem::TryPickUp`.
- `UUPCInteractorComponent::GatherCandidates`, `RankCandidates` (protected) and `FindCandidate` are virtual, for a detection rule of your own.
- `UUPCInteractAbility::ResolveInteractionTarget` and `ResolveInteractionSelection` are Blueprint native events for another focus system; the pawn still needs a UPC Interactor for its Detection Radius.
- `UUPCInteractionStatics::ExecuteInteractionSelection` (authority) runs a selection with a press's checks. An interaction run without the payload ability calls the Interactor's `NotifyInteractionStarted`, `NotifyInteractionCommitted` and `NotifyInteractionEnded`.

</details>

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

| Log or symptom | Fix |
| --- | --- |
| "Interaction option '...' on '...' is not offered" | The row lacks an Option Id, uses a tag outside `UPC.Input`, misses what its payload needs, or repeats an Option Id. Data Validation names it; the other rows still show. |
| "... is hidden and does not run: the character needs one grant of '...'" | Grant a Run Ability row's ability exactly once; keep the Interactor's Payload Ability Class set and granted nowhere else. |
| "'...' pressed interact but carries no UPC Interactor component" | Add a UPC Interactor to the pawn. |
| "'...' was granted with more than one UPC.Input tag" | Grant the interact ability once per tag. |
| The prompt never shows | With the overlay on, check Tracking, Detection Radius, Blocked Tags and Require Sight. |
| One placed actor ignores its Blueprint's options | It keeps its own copy of Options: click the revert arrow on **Options** in the level. |

</details>

---

Previous page: [Telegraphs](https://rigbak.com/docs/universal-player-combat/telegraphs). Next page: [Interaction Payloads](https://rigbak.com/docs/universal-player-combat/interaction-payloads)
