Interaction system

The interaction system is implemented in the PulseAbility module and centered around:

  • UPulseInteractAbility
  • UPulseAbilityTask_QueryInteractables
  • UPulseAbilityTask_ManageInteractables
  • IPulseInteractableInterface
  • UPulseInteractableComponent

Main runtime flow

At runtime, UPulseInteractAbility does the following:

  1. Activates locally and starts query/manage tasks (BeginQueryInteractables).
  2. Query task detects focused interactables (sphere/component overlap or trace).
  3. Manage task keeps a list of focused interactables and selects one by priority.
  4. Ability exposes focus/selection/interaction events.
  5. StartInteraction() and EndInteraction() call interface events on the selected target.

Core methods in UPulseInteractAbility:

  • ActivateAbility(...)
  • BeginQueryInteractables()
  • NewInteractableFocused(...)
  • InteractableFocusLost(...)
  • InteractableSelected(...)
  • StartInteraction()
  • EndInteraction()

Query modes

EPulseInteractQueryType supports three query strategies:

  1. BySphere
  2. ByComponent
  3. ByTrace

BySphere

  • Creates a transient USphereComponent on the interactor actor.
  • Uses overlap begin/end events to add/remove interactables.
  • Uses SphereQueryRadius and SphereQueryCollisionSettings.

ByComponent

  • Uses existing primitive components on the interactor.
  • Components are discovered by tag:
    • Pulse.Ability.Interact.InteractableComponent
  • Components must generate overlaps.

ByTrace

  • Performs periodic trace queries using FPulseTraceParams.
  • Supports sync and async trace (bAsyncTrace).
  • Start/end is provided by a trace location provider (UPulseTraceLocationProvider).

Supported provider classes include:

  • UPulseTraceLocationProvider_Default
  • UPulseTraceLocationProvider_Pawn
  • UPulseTraceLocationProvider_Camera
  • UPulseInteractTraceLocationProvider_BP

Focus, selection, and interaction semantics

Focused interactables

Query task stores currently focused actors/components and emits:

  • OnInteractableFound / OnInteractableLost interface callbacks
  • ability-side notifications (NewInteractableFocused, InteractableFocusLost)

Selected interactable

Manage task sorts focused interactables by prioritizer result and selects the highest one.

  • Old selected receives OnInteractableUnselected
  • New selected receives OnInteractableSelected

Interaction

StartInteraction():

  • Checks selected target.
  • Validates CanBeInteractedWith.
  • Sets InteractingActor / InteractingComponent.
  • Calls OnInteractionStarted.

EndInteraction():

  • Calls OnInteractionEnded.
  • Clears interacting references.

GetInteractionTime() returns elapsed seconds while actively interacting.

Interactable interface contract

IPulseInteractableInterface defines:

  • availability checks:
    • CanBeFocused
    • CanBeInteractedWith
  • lifecycle callbacks:
    • OnInteractableFound
    • OnInteractableLost
    • OnInteractableSelected
    • OnInteractableUnselected
    • OnInteractionStarted
    • OnInteractionEnded
  • priority/replication hooks:
    • GetInteractablePriority
    • ShouldReplicateInteraction

Important behavior:

  1. If actor implements the interface, actor-level interaction takes precedence.
  2. If only components implement it, component selection logic is applied.

Component selection for multi-component actors

When an actor has multiple interactable components, the ability resolves one active component using:

  • Blueprint override GetInteractableComponentToFocus_BP(...), or
  • UPulseInteractComponentSelector instance, or
  • fallback to first component

Built-in selectors:

  • UPulseInteractComponentSelector_Priority
  • UPulseInteractComponentSelector_Closest

Component changes while focused trigger:

  • ability callback InteractableComponentChanged(...)
  • old component OnInteractableLost
  • new component OnInteractableFound

Prioritization

Selection priority is handled by UPulseInteractPrioritizer.

Built-in options:

  1. UPulseInteractPrioritizer_Default (uses GetInteractablePriority)
  2. UPulseInteractPrioritizer_Closest (distance-based with optional look-at bonus)
  3. Blueprint extension via UPulseInteractPrioritizer_BP and UPulseInteractPrioritizer_Closest_BP

Gameplay tags and events

Declared in PulseInteractAbility.cpp / PulseInteractAbility.h:

  • Focus:
    • Pulse.Gameplay.Event.Interact.Focus.Gained
    • Pulse.Gameplay.Event.Interact.Focus.Lost
  • Selection:
    • Pulse.Gameplay.Event.Interact.Selected
  • Interaction:
    • Pulse.Gameplay.Event.Interact.Started
    • Pulse.Gameplay.Event.Interact.Ended
  • Component change:
    • Pulse.Gameplay.Event.Interact.Component.Changed
  • Trigger tags:
    • Pulse.Gameplay.Event.Interact.Started.Trigger
    • Pulse.Gameplay.Event.Interact.Ended.Trigger

When bSendGameplayEventOnInteractionEvent is enabled, ability emits gameplay events for focus/selection/interaction transitions.

Replicated interaction variant

UPulseRepInteractAbility extends UPulseInteractAbility and enables ReplicationPolicy = ReplicateYes.

Key points:

  1. Replication eligibility checks actor/component replication status.
  2. Replication intent is delegated to ShouldReplicateInteraction(...) on the interactable object.
  3. Start/end interaction has server RPC paths (ServerStartInteraction, ServerEndInteraction).

UI integration via MVVM

UMVVMPulseInteract (ModelViewViewModel) mirrors interaction state for UI:

  • InteractAbility
  • SelectedInteractable
  • bIsInteracting
  • FocusedInteractables (optional list mode)

It subscribes to native ability events:

  • OnInteractableFocusedNative
  • OnInteractableLostNative
  • OnInteractableSelectedNative
  • OnInteractionStartedNative
  • OnInteractionEndedNative
  • OnInteractableComponentChangedNative

This gives a clean binding surface for interaction prompts and status widgets without polling.


PulseCore plugin documentation.

This site uses Just the Docs, a documentation theme for Jekyll.