Interaction system
The interaction system is implemented in the PulseAbility module and centered around:
UPulseInteractAbilityUPulseAbilityTask_QueryInteractablesUPulseAbilityTask_ManageInteractablesIPulseInteractableInterfaceUPulseInteractableComponent
Main runtime flow
At runtime, UPulseInteractAbility does the following:
- Activates locally and starts query/manage tasks (
BeginQueryInteractables). - Query task detects focused interactables (sphere/component overlap or trace).
- Manage task keeps a list of focused interactables and selects one by priority.
- Ability exposes focus/selection/interaction events.
StartInteraction()andEndInteraction()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:
BySphereByComponentByTrace
BySphere
- Creates a transient
USphereComponenton the interactor actor. - Uses overlap begin/end events to add/remove interactables.
- Uses
SphereQueryRadiusandSphereQueryCollisionSettings.
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_DefaultUPulseTraceLocationProvider_PawnUPulseTraceLocationProvider_CameraUPulseInteractTraceLocationProvider_BP
Focus, selection, and interaction semantics
Focused interactables
Query task stores currently focused actors/components and emits:
OnInteractableFound/OnInteractableLostinterface 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:
CanBeFocusedCanBeInteractedWith
- lifecycle callbacks:
OnInteractableFoundOnInteractableLostOnInteractableSelectedOnInteractableUnselectedOnInteractionStartedOnInteractionEnded
- priority/replication hooks:
GetInteractablePriorityShouldReplicateInteraction
Important behavior:
- If actor implements the interface, actor-level interaction takes precedence.
- 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 UPulseInteractComponentSelectorinstance, or- fallback to first component
Built-in selectors:
UPulseInteractComponentSelector_PriorityUPulseInteractComponentSelector_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:
UPulseInteractPrioritizer_Default(usesGetInteractablePriority)UPulseInteractPrioritizer_Closest(distance-based with optional look-at bonus)- Blueprint extension via
UPulseInteractPrioritizer_BPandUPulseInteractPrioritizer_Closest_BP
Gameplay tags and events
Declared in PulseInteractAbility.cpp / PulseInteractAbility.h:
- Focus:
Pulse.Gameplay.Event.Interact.Focus.GainedPulse.Gameplay.Event.Interact.Focus.Lost
- Selection:
Pulse.Gameplay.Event.Interact.Selected
- Interaction:
Pulse.Gameplay.Event.Interact.StartedPulse.Gameplay.Event.Interact.Ended
- Component change:
Pulse.Gameplay.Event.Interact.Component.Changed
- Trigger tags:
Pulse.Gameplay.Event.Interact.Started.TriggerPulse.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:
- Replication eligibility checks actor/component replication status.
- Replication intent is delegated to
ShouldReplicateInteraction(...)on the interactable object. - Start/end interaction has server RPC paths (
ServerStartInteraction,ServerEndInteraction).
UI integration via MVVM
UMVVMPulseInteract (ModelViewViewModel) mirrors interaction state for UI:
InteractAbilitySelectedInteractablebIsInteractingFocusedInteractables(optional list mode)
It subscribes to native ability events:
OnInteractableFocusedNativeOnInteractableLostNativeOnInteractableSelectedNativeOnInteractionStartedNativeOnInteractionEndedNativeOnInteractableComponentChangedNative
This gives a clean binding surface for interaction prompts and status widgets without polling.