Skip to main content

API Reference

Complete reference for public classes, interfaces, and events in ElysAwareness.

Core Components​

UERPAwarenessComponent​

Main perception component managing multi-channel pipeline execution.

Header: Core/ERPAwarenessComponent.h

Properties​

PropertyTypeDefaultDescription
PerceptionTickIntervalfloat0.0Tick interval in seconds (0 = every frame)
DefaultSamplingRangefloat2000.0Default sampling range (cm) passed to samplers
ChannelPipelinesTArray<FERPChannelPipeline>Multi-channel pipeline configuration
bProvideViewportInfoWhenAvailableboolfalseInclude viewport size and screen reference in context
DefaultScreenReferenceNdcFVector2D(0.5, 0.5)Default screen reference (normalized 0..1)
bEvaluateOnlyForLocalControllerbooltrueOnly tick for the local player (multiplayer)
bDebugPerceptionboolfalseEnable debug logging
DebugPerceptionIntervalSecondsfloat0.0Debug log throttle interval

Methods​

AActor* GetChannelCandidate(FName ChannelId) const;
bool HasChannelCandidate(FName ChannelId) const;
void GetAllChannelCandidates(TArray<FName>& OutChannelIds, TArray<AActor*>& OutCandidates) const;
bool ValidateActorForChannel(AActor* Actor, FName ChannelId) const;

Events​

FERPOnChannelCandidateAcquiredSignature OnChannelCandidateAcquired; // (FName ChannelId, AActor* Candidate)
FERPOnChannelCandidateLostSignature OnChannelCandidateLost; // (FName ChannelId, AActor* Candidate)
FERPOnChannelEvaluatedSignature OnChannelEvaluated; // (FName ChannelId, TArray<FERPPipelineScoredCandidate>)

OnChannelEvaluated fires after each evaluation with ALL scored candidates (post-filter, post-scoring). Use this for minimap markers, radar, or any UI that needs the full candidate set.

Evaluation Lifecycle​

When awareness evaluation becomes unavailable (for example, the owning pawn loses its local controller while entering a vehicle), every current channel candidate is cleared and OnChannelCandidateLost is emitted once for each valid candidate. Candidate maps are emptied before the events are broadcast, so queries made from an event handler already observe the cleared state.

This is a lifecycle transition, not a paused evaluation: interaction prompts, focus outlines, and other channel feedback must not remain latched to the previously controlled pawn. A later local evaluation can acquire candidates normally again.

Overridable Functions​

void GetPerceptionAimRay(FVector& OutOrigin, FVector& OutDirection) const;
bool GetScreenReferenceNdc(FVector2D& OutScreenReferenceNdc) const;

UERPDomainComponent (Abstract)​

Base class for gameplay domain components that consume perception events.

Header: Core/ERPDomainComponent.h

Properties​

PropertyTypeDefaultDescription
PerceptionComponentUERPAwarenessComponent*nullptrAuto-found on owner at BeginPlay
ChannelIdFNameNonePerception channel to listen to

Methods​

AActor* GetCurrentCandidate() const;
bool HasCandidate() const;
void SetCandidate(AActor* Candidate);
void ClearCandidate();

Events​

FERPOnDomainCandidateChangedSignature OnDomainCandidateChanged; // (AActor* Previous, AActor* New, FName ChannelId)

EndPlay clears the active candidate before the domain component unsubscribes from awareness events. Derived C++ components that override EndPlay must call Super::EndPlay so candidate-specific feedback is released during destruction, pawn replacement, and level teardown.

Virtual Hooks (BlueprintNativeEvent)​

bool IsCandidateEligible(AActor* Candidate) const;           // Default: true
void HandleCandidateUpdated(AActor* Previous, AActor* Current); // Default: no-op

UERPInteractionComponent​

Interaction domain extending UERPDomainComponent. Adds multi-action descriptor support, challenge lifecycle management, wheel mode, and RPC networking.

When the candidate changes, the component automatically looks for UERPInteractableComponent on the candidate actor. If found, it calls SetInteractionFocused and UpdateInteractionDescriptor. If not found, use OnDescriptorChanged / OnDomainCandidateChanged to drive your own UI.

Header: Domains/Interaction/ERPInteractionComponent.h

Properties​

PropertyTypeDefaultDescription
RulesTArray<UERPInteractionRule*>Instanced validation rules
MaxInteractionDistancefloat500.0Server-side distance validation (cm)
bSuppressMovementInputDuringScreenChallengesbooltruePrevent modal directional challenge input from moving the pawn
bSuppressLookInputDuringScreenChallengesboolfalseOptionally suppress camera input during modal challenges

Methods​

// State
void GetCurrentDescriptor(FERPInteractionDescriptor& OutDescriptor) const;
bool HasDescriptor() const;
bool HasActiveChallenge() const;
bool IsChallengeInputSuppressed() const;
void ForceRefreshDescriptor(); // Re-pull from current candidate; broadcasts if changed

// Interaction attempt (call from input bindings)
void StartInteractionAttempt(const UInputAction* TriggeredAction = nullptr);
void StopInteractionAttempt(const UInputAction* TriggeredAction = nullptr);
void ResetInteractionAttempt(); // Forcibly cancel; use on stun/death

// Wheel API (call from wheel widget)
void SubmitWheelSelection(const UInputAction* SelectedAction);
void CancelWheelSelection();

// Cooldown queries
bool IsActionOnCooldown(const UInputAction* InputAction) const;
// Returns true if the specified action is currently on cooldown.

float GetActionCooldownRemaining(const UInputAction* InputAction) const;
// Returns remaining cooldown time in seconds (0 if not on cooldown).

StartInteractionAttempt(IA) dispatches based on the descriptor:

  • Wheel mode (Actions.Num() > 1, Wheel): fires OnWheelRequested(Actions), ignores TriggeredAction
  • Simple press (no Challenge): executes immediately
  • Challenge present: starts the challenge (DuplicateObject per attempt)

Passing null uses the primary action (Actions[0]).

Events​

FERPOnInteractionDescriptorChangedSignature OnDescriptorChanged;
// (AActor* Candidate, const FERPInteractionDescriptor& Descriptor, FName ChannelId)

FERPOnInteractionExecutedSignature OnInteractionExecuted;
// (AActor* InteractableActor)

FERPOnInteractionFailedSignature OnInteractionFailed;
// (AActor* InteractableActor, const FString& Reason)

FERPOnInteractionProgressSignature OnInteractionProgress;
// (const UInputAction* Action, float Progress)
// Action identifies which action's challenge is progressing. Progress is 0..1.

FERPOnWheelRequestedSignature OnWheelRequested;
// (const TArray<FERPInteractionAction>& Actions)
// Fired when wheel mode is triggered. Bind in your HUD to open the wheel widget.

FERPOnWheelDismissedSignature OnWheelDismissed;
// (bool bCancelled)
// Fired when the wheel closes (via SubmitWheelSelection or CancelWheelSelection).

ForceRefreshDescriptor​

Call when an interactable changes its descriptor while remaining the active candidate (e.g., a door goes from "Open" to "Locked"). Perception only fires events on candidate transitions — it does not detect data changes on the same actor.

ForceRefreshDescriptor() re-pulls GetInteractionDescriptor from the current candidate and, if the descriptor changed:

  • Broadcasts OnDescriptorChanged
  • Notifies UERPInteractableComponent on the candidate (if present)

RPCs (internal)​

Server_RequestInteraction(AActor*, int32 ActionIndex)  // Server RPC with validation
Client_OnInteractionSuccess(AActor*) // Client notification
Client_OnInteractionFailed(AActor*, const FString&) // Client notification

ActionIndex is resolved client-side from UInputAction* before the RPC, avoiding UObject pointer serialization across the network.


UERPTargetingComponent​

Targeting domain extending UERPDomainComponent.

Header: Domains/Targeting/ERPTargetingComponent.h

Properties​

PropertyTypeDefaultDescription
RulesTArray<UERPTargetRule*>Instanced validation rules

Methods​

const FERPTargetDescriptor& GetCurrentDescriptor() const;
AActor* GetLockedTarget() const;
void ToggleLockOn();
bool LockOnClosestTarget();
void CycleTarget(bool bNext = true);

ToggleLockOn() uses the awareness pipeline's current screen-focused candidate. It locks or transfers to that actor, and unlocks only when the same actor is already hard-locked. LockOnClosestTarget() independently selects by world distance among cached eligible candidates. When the component belongs to a PlayerController, range and nearest-target calculations use the possessed pawn's position rather than the controller actor's location; Pawn-owned and Actor-owned components use their owner position. CycleTarget() moves to the next or previous eligible candidate and hard-locks it; from automatic mode it cycles relative to the current soft focus rather than duplicating closest-target selection.

Events​

FERPOnTargetDescriptorChangedSignature OnDescriptorChanged; // (AActor*, const FERPTargetDescriptor&, FName ChannelId)

UERPChannelListenerComponent​

Lightweight single-channel event mirror. No domain logic.

Header: Core/ERPChannelListenerComponent.h

Methods​

AActor* GetCurrentCandidate() const;
bool HasCandidate() const;
void SetPerceptionComponent(UERPAwarenessComponent* InPerceptionComponent);
void SetChannelId(FName InChannelId);

Events​

FERPOnCandidateAcquiredSignature OnCandidateAcquired; // (AActor*)
FERPOnCandidateLostSignature OnCandidateLost; // (AActor*)

UERPInteractableComponent​

All-in-one interactable component: implements IERPInteractable + manages visual feedback (outline + widget).

Header: Domains/Interaction/ERPInteractableComponent.h

Properties — Descriptor​

PropertyTypeDescription
DefaultDescriptorFERPInteractionDescriptorUsed when BuildDescriptor is not bound
CanInteractCheckFERPCanInteractCheckDelegateRuntime override for CanBeInteractedWith
BuildDescriptorFERPBuildDescriptorDelegateRuntime override for descriptor

Properties — Widget Classes​

PropertyTypeDescription
SingleActionWidgetClassTSubclassOf<UERPInteractionWidgetBase>1 action
MultiActionWidgetClassTSubclassOf<UERPInteractionWidgetBase>2+ actions, DirectKeys
WheelWidgetClassTSubclassOf<UERPInteractionWidgetBase>2+ actions, Wheel
AmbientWidgetClassTSubclassOf<UERPInteractionWidgetBase>Always-on world marker (optional)
WidgetClassOverrideTSubclassOf<UERPInteractionWidgetBase>Overrides all of the above

Properties — Placement​

PropertyTypeDefaultDescription
WidgetOffsetFVector(0,0,0)Offset from attachment point
WidgetAnchorTagFNameERP_WidgetAnchorComponent tag for custom anchor
WidgetSpaceEWidgetSpaceScreenScreen or World space

Properties — Feedback​

PropertyTypeDefaultDescription
bEnableCustomDepthFeedbackbooltrueOutline on focus
CustomDepthStencilValueint321Stencil value

Events​

FERPOnInteractedSignature OnInteracted; // (AActor* InteractingActor, int32 ActionIndex)

Methods (Feedback API — called by ERPInteractionComponent)​

void SetInteractionFocused(APlayerController* PC, bool bFocused);
void UpdateInteractionDescriptor(APlayerController* PC, const FERPInteractionDescriptor& Descriptor);
void UpdateInteractionProgress(APlayerController* PC, const UInputAction* Action, float Progress);
bool IsInteractionFocused() const;
void ApplyDefaultCustomDepthFeedback(bool bEnable);
UWidgetComponent* GetInteractionWidgetComponent() const;
UWidgetComponent* GetAmbientWidgetComponent() const;

Blueprint NativeEvents​

void OnInteractionFocused(APlayerController* PC, bool bFocused);
void OnDescriptorUpdated(APlayerController* PC, const FERPInteractionDescriptor& Descriptor);
void OnInteractionProgress(APlayerController* PC, const UInputAction* Action, float Progress);

UERPCandidateRegistrySubsystem​

World-level registry for declarative candidate registration (non-spatial perception).

Header: Core/ERPCandidateRegistrySubsystem.h

Methods​

void RegisterActor(FName ChannelId, AActor* Actor);
void UnregisterActor(FName ChannelId, AActor* Actor);
void UnregisterFromAll(AActor* Actor);
TArray<AActor*> GetRegisteredActors(FName ChannelId);
bool HasRegisteredActors(FName ChannelId) const;
bool IsActorRegistered(FName ChannelId, AActor* Actor) const;

Events​

FERPOnActorRegisteredSignature OnActorRegistered;     // (FName ChannelId, AActor* Actor)
FERPOnActorUnregisteredSignature OnActorUnregistered; // (FName ChannelId, AActor* Actor)

UERPRegistrationComponent​

Auto-registers the owning actor in the candidate registry on BeginPlay/EndPlay.

Header: Core/ERPRegistrationComponent.h

Properties​

PropertyTypeDefaultDescription
ChannelIdsTArray<FName>Channels to register for

Methods​

void RegisterChannel(FName ChannelId);
void UnregisterChannel(FName ChannelId);

Widget Base Classes​

UERPInteractionWidgetBase (Abstract)​

Base widget for all interaction prompt types: single action, multi-action list, and wheel.

Header: UI/Interaction/ERPInteractionWidgetBase.h

Methods​

void UpdateFromDescriptor(const FERPInteractionDescriptor& Descriptor);
// Caches descriptor, calls OnDescriptorUpdated and OnActionsUpdated.

void SetFocused(bool bNewFocused);
// Calls OnFocusChanged.

void OnActionProgressChanged(const UInputAction* Action, float Progress);
// Forwards to OnActionProgress. Called by UERPInteractableComponent.

const FERPInteractionDescriptor& GetDescriptor() const;
bool IsFocused() const;

FText GetInputActionDisplayKey(const UInputAction* InputAction) const;
// Returns the bound key text from Enhanced Input (e.g. "E"). Returns "?" if not found.

FText GetPrimaryActionDisplayKey() const;
// Shortcut: key for Actions[0].InputAction. Returns "?" if no primary action.

Blueprint NativeEvents​

void OnDescriptorUpdated(const FERPInteractionDescriptor& Descriptor);
// Default: no-op. Override to refresh ObjectName, ObjectDescription, ObjectIcon.

void OnActionsUpdated(const TArray<FERPInteractionAction>& Actions);
// Default: no-op. Override to build action rows (multi-action) or wheel slices.

void OnActionProgress(const UInputAction* Action, float Progress);
// Default: no-op. Override to route progress to the matching challenge sub-widget.
// Action identifies which action is progressing. Progress is 0..1.

void OnFocusChanged(bool bNewFocused);
// Default: toggles visibility (HitTestInvisible / Collapsed).

UERPChallengeWidgetBase (Abstract)​

Base widget for challenge progress display (hold ring, press counter, timing bar).

Intended to be embedded inside an interaction prompt widget as a sub-widget per action row. The parent widget calls SetChallengeProgress(Progress) in its OnActionProgress override.

Header: UI/Interaction/ERPChallengeWidgetBase.h

Methods​

void SetChallengeProgress(float InProgress);    // 0..1
void NotifyChallengeComplete(bool bSuccess);
void ResetChallenge();
float GetChallengeProgress() const;

Blueprint NativeEvents​

void OnChallengeProgressChanged(float Progress); // Default: no-op
void OnChallengeCompleted(bool bSuccess); // Default: no-op
void OnChallengeReset(); // Default: no-op

UERPTargetingWidgetBase (Abstract)​

Base widget for targeting UI (reticles, lock-on indicators, info panels).

Header: UI/Targeting/ERPTargetingWidgetBase.h

Methods​

void UpdateFromDescriptor(const FERPTargetDescriptor& Descriptor);
void SetTargetActive(bool bActive);
void SetTargetActor(AActor* Actor);
const FERPTargetDescriptor& GetDescriptor() const;
bool IsTargetActive() const;
AActor* GetTargetActor() const;

Blueprint NativeEvents​

void OnDescriptorUpdated(const FERPTargetDescriptor& Descriptor);
void OnTargetActiveChanged(bool bActive); // Default: toggle visibility
void OnTargetActorChanged(AActor* NewTargetActor);

Concrete Interaction Widgets​

ClassHeaderParentDescription
UERPBaseMultiPressChallengeWidgetUI/Interaction/ERPBaseMultiPressChallengeWidget.hUERPChallengeWidgetBaseContinuous pressure meter for repeated input
UERPBaseRadialHoldWidgetUI/Interaction/ERPBaseRadialHoldWidget.hUERPChallengeWidgetBaseCircular fill hold challenge (MID-driven)
UERPBaseWorldInteractionWidgetUI/Interaction/ERPBaseWorldInteractionWidget.hUERPInteractionWidgetBaseWorld-space prompt for interactable actors
UERPBaseTimedPressChallengeWidgetUI/Interaction/ERPBaseTimedPressChallengeWidget.hUERPChallengeWidgetBaseCountdown bar + key prompt (QTE timed press)
UERPBaseTimingChallengeWidgetUI/Interaction/ERPBaseTimingChallengeWidget.hUERPChallengeWidgetBaseTrack with moving cursor + target zone (QTE timing)
UERPBaseAlternatingPressChallengeWidgetUI/Interaction/ERPBaseAlternatingPressChallengeWidget.hUERPChallengeWidgetBaseArrow-only alternating pressure gauge
UERPBaseSequenceChallengeWidgetUI/Interaction/ERPBaseSequenceChallengeWidget.hUERPChallengeWidgetBaseCenter-screen directional-sequence QTE
UERPBaseRhythmChallengeWidgetUI/Interaction/ERPBaseRhythmChallengeWidget.hUERPChallengeWidgetBaseRight-to-left rhythm lane with a fixed hit marker

Concrete Targeting Widgets​

ClassHeaderParentDescription
UERPBaseTargetFrameWidgetUI/Targeting/ERPBaseTargetFrameWidget.hUERPTargetingWidgetBaseHUD nameplate (name + icon + tag coloring)
UERPBaseTargetHealthBarWidgetUI/Targeting/ERPBaseTargetHealthBarWidget.hUERPBaseTargetFrameWidgetNameplate + health bar
UERPBaseTargetReticleWidgetUI/Targeting/ERPBaseTargetReticleWidget.hUERPTargetingWidgetBaseWorld-space lock-on reticle

See Built-in Widgets for full style property tables and layout details.


Interfaces​

IERPInteractable​

Header: Domains/Interaction/ERPInteractable.h

// Is this object currently interactable? Called frequently — keep it lightweight.
bool CanBeInteractedWith(AActor* InteractingActor) const;

// Fill the descriptor with all available actions, object identity, and mode.
void GetInteractionDescriptor(FERPInteractionDescriptor& OutDescriptor) const;

// Execute action at the given index. Called on the SERVER.
// ActionIndex is the index into Descriptor.Actions. Pass INDEX_NONE or 0 for primary.
// Return true on success, false on failure.
bool ExecuteInteraction(AActor* InstigatorActor, int32 ActionIndex);

IERPTargetable​

Header: Domains/Targeting/ERPTargetable.h

bool CanBeTargetedBy(AActor* TargetingActor) const;
UERPTargetDescriptor* GetTargetDescriptor() const;

Challenges​

UERPInteractionChallenge (Abstract)​

Base class for interaction challenges. Subclass to create custom challenge types.

Header: Domains/Interaction/Challenges/ERPInteractionChallenge.h

Challenges are instanced on FERPInteractionAction.Challenge. The interaction component creates a DuplicateObject per attempt to avoid shared mutable state across concurrent players.

Properties​

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Challenge")
TSubclassOf<UERPChallengeWidgetBase> WidgetClass;
// Optional: widget class for displaying this challenge's progress.

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Challenge|Presentation")
EERPChallengePresentationMode PresentationMode;
// InteractionPrompt for inline hold feedback; ScreenOverlay for centered skill checks.

WidgetClass is optional. When UERPInteractionComponent::bAutoCreateChallengeWidget is enabled, the component owns the widget lifecycle for the local player. Set the flag to false to keep challenge mechanics while presenting progress through a custom HUD.

Methods (BlueprintNativeEvent)​

void StartChallenge();     // Called when the attempt begins
void OnInputPressed(); // Called when the action input is pressed
void OnInputActionPressed(const UInputAction* InputAction); // Input-aware QTE event
void OnInputReleased(); // Called when the action input is released
void OnInputActionReleased(const UInputAction* InputAction);
void TickChallenge(float DeltaTime); // Called each frame during an active challenge
void Reset(); // Called to reset state for a new attempt

Events​

FERPOnChallengeProgressSignature OnProgress; // (float Progress) — 0..1
FERPOnChallengeCompleteSignature OnComplete; // (bool bSuccess)
FERPOnChallengeStepChangedSignature OnStepChanged;
// (int32 CurrentStepIndex, int32 TotalSteps) — zero-based active step.
// CurrentStepIndex equals TotalSteps after successful completion.

UERPHoldChallenge​

Hold the action key for a fixed duration.

Header: Domains/Interaction/Challenges/ERPHoldChallenge.h

Properties​

PropertyTypeDefaultDescription
HoldDurationfloat1.5Hold time in seconds

Behavior:

  • StartChallenge: begins accumulating time
  • OnInputReleased: resets accumulated time, fires OnProgress(0)
  • TickChallenge: advances progress; fires OnComplete(true) when duration reached

UERPMultiPressChallenge​

Press the action key N times.

Header: Domains/Interaction/Challenges/ERPMultiPressChallenge.h

Properties​

PropertyTypeDefaultDescription
RequiredPressesint325Number of presses to complete
PressCooldownfloat0.0Minimum time between valid presses (seconds) — useful for animation sync
DecayPerSecondfloat0.0Progress lost per second when not pressing — creates mash decay pressure

Behavior:

  • OnInputPressed: increments press count (if cooldown elapsed), fires OnProgress; fires OnComplete(true) when count reached
  • TickChallenge: applies DecayPerSecond (reduces progress toward 0 if not pressing)

UERPAlternatingPressChallenge​

Alternate two input actions to fill a pressure gauge. Repeating the same side is ignored; this is a continuous, recoverable challenge rather than an ordered QTE.

Header: Domains/Interaction/Challenges/ERPAlternatingPressChallenge.h

Properties​

PropertyTypeDefaultDescription
LeftActionUInputAction*nullInput action for the left side
RightActionUInputAction*nullInput action for the right side
RequiredInputsint3212Difficulty: valid alternating inputs needed to fill the gauge
DecayPerSecondfloat0.0Difficulty: gauge units lost per second
PressCooldownfloat0.0Minimum interval between accepted inputs
bStartWithLeftbooltrueSelects the first expected side

Increasing RequiredInputs lengthens the challenge. Increasing DecayPerSecond raises the minimum sustained input rate. The two values are independent so designers can create a long forgiving challenge, a short intense challenge, or anything between them.


UERPTimedPressChallenge​

Press the action key before a countdown expires.

Header: Domains/Interaction/Challenges/ERPTimedPressChallenge.h

Properties​

PropertyTypeDefaultDescription
TimeWindowfloat3.0Seconds before the challenge fails

Behavior:

  • StartChallenge: begins countdown timer
  • OnInputPressed: if timer hasn't expired, fires OnComplete(true)
  • TickChallenge: advances timer; fires OnProgress with value counting down from 1 to 0; fires OnComplete(false) on timeout

UERPSequenceChallenge​

Press a series of input actions in the correct order.

Header: Domains/Interaction/Challenges/ERPSequenceChallenge.h

Properties​

PropertyTypeDefaultDescription
SequenceTArray<UInputAction*>Ordered list of input actions to press
bFailOnWrongKeyboolfalseFail immediately instead of resetting on wrong key press
TimeLimitfloat0.0Max seconds to complete the sequence (0 = no limit)

Methods​

int32 GetCurrentKeyIndex() const;
// Returns the index of the next key the player must press (0-based).

const UInputAction* GetNextExpectedAction() const;
// Returns the UInputAction the player must press next, or null if complete.

int32 GetTotalStepCount() const;
float GetRemainingTime() const;
float GetNormalizedTimeRemaining() const;
bool IsActive() const;

Behavior:

  • OnInputActionPressed: checks the concrete action against Sequence[CurrentIndex]; advances on match, fails or resets on mismatch according to bFailOnWrongKey
  • OnStepChanged: fires at start, reset, and every accepted step; completion reports (TotalSteps, TotalSteps)
  • OnCountdownChanged: reports (RemainingSeconds, NormalizedRemaining) while TimeLimit > 0
  • TickChallenge: updates the countdown and fires OnComplete(false) on timeout
  • Progress = completed keys / total keys

UERPTimingChallenge​

Press when a moving cursor lands inside a target zone on a track.

Header: Domains/Interaction/Challenges/ERPTimingChallenge.h

Properties​

PropertyTypeDefaultDescription
CursorSpeedfloat1.0Cursor speed in normalized track lengths per second
TargetCenterfloat0.5Center of the target zone (0..1)
TargetHalfWidthfloat0.1Half-width of the target zone
bFailOnMissboolfalseFail immediately if the player presses outside the zone
RequiredHitsint321Successful hits needed to complete
TargetSequenceTArray<float>EmptyOptional normalized target centers for multi-hit challenges
SpeedIncreasePerHitfloat0.0Additional cursor speed after each successful hit

Methods​

float GetCursorPosition() const;
// Returns the current cursor position on the track (0..1).

bool IsCursorInTargetZone() const;
// Returns true if the cursor is currently within the target zone.

Behavior:

  • TickChallenge: oscillates cursor position between 0 and 1
  • OnInputPressed: checks if cursor is in target zone; increments hit count on success, fails on miss if bFailOnMiss
  • Progress = current hits / required hits
  • Fires OnComplete(true) when RequiredHits reached

UERPRhythmChallenge​

Matches concrete input actions against notes that reach a fixed hit time from right to left.

Header: Domains/Interaction/Challenges/ERPRhythmChallenge.h

PropertyTypeDefaultDescription
BeatActionsTArray<UInputAction*>EmptyOrdered input action for each beat
BeatIntervalfloat0.7Seconds between beats
ApproachDurationfloat2.0Travel time from lane entry to hit marker
HitWindowfloat0.18Allowed early/late timing in seconds
bFailOnWrongInputbooltrueFail on an unexpected action
bFailOnMissbooltrueFail after a beat leaves its hit window

GetCurrentBeatIndex(), GetTotalBeatCount(), GetElapsedTime(), GetBeatTime(), and GetBeatApproachAlpha() expose presentation state to Blueprint widgets. OnStepChanged fires at start, reset, and whenever a beat is accepted or skipped; completion reports (TotalSteps, TotalSteps). Progress continues to expose the overall timeline, while completion uses the standard challenge delegate.


Pipeline Base Classes​

UERPSamplerBase​

void Sample(const FERPAwarenessContext& Context, float Range, TArray<AActor*>& OutCandidates) const;

UERPFilterBase​

bool Passes(const FERPAwarenessContext& Context, AActor* Candidate) const;

UERPScorerBase​

float Score(const FERPAwarenessContext& Context, AActor* Candidate) const;

EERPResolverPolicy (Enum)​

enum class EERPResolverPolicy : uint8
{
LowestScore, // Lowest aggregated score wins (default)
HighestScore, // Highest aggregated score wins
};

Data Structures​

FERPInteractionDescriptor​

Pure runtime data contract for an interactable and its available actions.

Header: Domains/Interaction/ERPInteractionDescriptor.h

struct FERPInteractionDescriptor
{
// Object identity
FText ObjectName; // "Wooden Door", "Iron Chest"
FText ObjectDescription; // Shown in rich tooltips / wheel center
TSoftObjectPtr<UTexture2D> ObjectIcon; // Resolve soft ref in widget when needed

// Actions
TArray<FERPInteractionAction> Actions; // [0] = primary action
EERPMultiActionMode MultiActionMode; // DirectKeys or Wheel

// Metadata
FGameplayTagContainer InteractionTags;

// Helpers
bool IsValid() const; // Actions.Num() > 0
const FERPInteractionAction* GetPrimaryAction() const; // Actions[0] or null
const FERPInteractionAction* FindAction(const UInputAction* IA) const;
int32 FindActionIndex(const UInputAction* IA) const;
bool operator==(const FERPInteractionDescriptor& Other) const;
};

FERPInteractionAction​

One interaction action within a descriptor.

Header: Domains/Interaction/ERPInteractionAction.h

struct FERPInteractionAction
{
FText ActionName; // "Open", "Inspect", "Loot"
FText ActionDescription; // Tooltip for this action
TSoftObjectPtr<UTexture2D> ActionIcon; // Per-action icon

TObjectPtr<const UInputAction> InputAction; // Key binding reference; also used as identifier
// In DirectKeys mode: player presses this key to trigger this action.
// In Wheel mode: used as identifier; SubmitWheelSelection(InputAction) dispatches to this action.
// In Server RPC: resolved to ActionIndex (int32) client-side before serialization.

TObjectPtr<UERPInteractionChallenge> Challenge; // Instanced (EditInlineNew).
// null = simple press (instant execution).
// Set UERPHoldChallenge, UERPMultiPressChallenge, or a custom subclass.

float Cooldown = 0.0f; // Seconds before this action can be used again (0 = no cooldown)
EERPCooldownScope CooldownScope = EERPCooldownScope::ThisAction;
// ThisAction: only this action is blocked during cooldown.
// AllActions: all actions on this interactable are blocked (widget hides).

bool IsSimplePress() const { return Challenge == nullptr; }
};

EERPMultiActionMode​

enum class EERPMultiActionMode : uint8
{
DirectKeys, // Each action has its own key. Player presses the matching key.
Wheel, // A single input opens a radial wheel. Player selects with stick or mouse.
};

EERPCooldownScope​

enum class EERPCooldownScope : uint8
{
ThisAction, // Only this action is disabled during cooldown. Other actions remain available.
AllActions, // All actions on this interactable are blocked. The widget hides entirely.
};

FERPAwarenessContext​

struct FERPAwarenessContext
{
FName ChannelId;
AActor* ContextActor;
FVector Origin;
FVector Forward;
bool bHasAimRay;
FVector AimOrigin;
FVector AimDirection;
bool bHasViewport;
FVector2D ViewportSizePx;
bool bHasScreenReference;
FVector2D ScreenReferenceNdc; // Normalized 0..1
APlayerController* ScreenProjectionPC;
};

FERPScorerEntry​

struct FERPScorerEntry
{
UERPScorerBase* Scorer;
float Weight = 1.0f;
};

FERPChannelPipeline​

struct FERPChannelPipeline
{
FName ChannelId;
FName SamplerCacheId; // Optional: force cache sharing across channels
UERPSamplerBase* Sampler;
TArray<UERPFilterBase*> Filters;
TArray<FERPScorerEntry> Scorers;
EERPResolverPolicy ResolverPolicy; // LowestScore (default) or HighestScore
float StickyBias = 0.1f; // Hysteresis bias (0 = disabled)
};

Aggregation is always a built-in weighted average. There is no separate aggregator or resolver class.


Default Implementations​

Samplers​

  • UERPSphereOverlapSampler — Sphere object-overlap query (spatial, range-limited; defaults to WorldDynamic)
  • UERPBoxOverlapSampler — Box overlap query (non-uniform spatial areas)
  • UERPRegistrySampler — Registry-based query (non-spatial, declarative)

Filters​

  • UERPTargetableFilter — Requires IERPTargetable
  • UERPInteractableFilter — Requires IERPInteractable
  • UERPDistanceFilter — Range-based filtering
  • UERPImplementsInterfaceFilter — Generic interface check
  • UERPConeFilter — Angle from forward direction
  • UERPLineOfSightFilter — Visibility trace from the awareness origin to the centre of candidate colliding bounds
  • UERPGameplayTagFilter — Gameplay tag matching

Scorers​

  • UERPDistanceScorer — Distance-based (lower = closer = better)
  • UERPConeScorer — Angle from forward direction
  • UERPDotProductScorer — Dot product scoring
  • UERPViewportEllipseScorer — Screen-space ellipse using candidate bounds centre (requires bProvideViewportInfoWhenAvailable)

Validation Rules​

  • UERPInteractionRule — Base for interaction validation rules
  • UERPTargetRule — Base for targeting validation rules

Instanced Interaction​

UERPInstancedInteractionComponent​

Player-side component that scans for nearby ISMC/HISMC instances and spawns actors to replace them. Supports two actor types: AERPInstanceProxy (full state machine + interaction) and any AActor with optional IERPInstanceStateReceiver interface.

Header: Domains/InstancedInteraction/ERPInstancedInteractionComponent.h

Properties​

PropertyTypeDefaultDescription
MeshConfigTableUDataTable*nullDataTable (row type: FERPInstancedMeshConfig) defining which meshes are interactable
SwapRadiusfloat600.0Radius (cm) around the owning pawn to scan for instances
DespawnMarginfloat200.0Extra margin added to SwapRadius for despawning (prevents flickering at boundary)
ScanIntervalfloat0.2How often to scan for instances (seconds)

Events​

FERPOnInstanceActorStateChanged OnInstanceActorStateChanged;
// (AActor* SpawnedActor, FGameplayTag StateTag, int32 StepIndex, const FERPInstanceKey& InstanceKey)
// Fired when an actor is spawned or changes state as an ISMC instance replacement.
// Works for both AERPInstanceProxy and generic actors.

AERPInstanceProxy​

Minimal actor spawned at the world transform of an ISMC/HISMC instance to make it individually interactable. Implements IERPInstanceStateReceiver. Subclass in Blueprint to override events.

Header: Domains/InstancedInteraction/ERPInstanceProxy.h

Components​

ComponentTypeDescription
MeshComponentUStaticMeshComponent*Root component. Mesh set automatically per state step
InteractableComponentUERPInteractableComponent*Handles interaction focus, widget display, and descriptor

Properties​

PropertyTypeDefaultDescription
StateStepsTArray<FERPInstanceStateStep>Ordered state lifecycle. Transitions via interaction (Duration=0) or auto-timer (Duration>0)

Methods​

// Initialization (called by UERPInstancedInteractionComponent)
void InitializeProxy(const FERPInstanceKey& InKey, const FTransform& InOriginalTransform, int32 InitialStepIndex);

// Accessors
const FERPInstanceKey& GetInstanceKey() const;
FGameplayTag GetCurrentStateTag() const;
int32 GetCurrentStepIndex() const;
const FTransform& GetOriginalTransform() const;
bool IsInteractable() const; // True if current step has actions
const TArray<FERPInstanceStateStep>& GetStateSteps() const;
void SetStateSteps(const TArray<FERPInstanceStateStep>& InSteps);

// State management
void AdvanceState(); // Next step in array (or loop if bLoopToFirst)
void SetStateByIndex(int32 StepIndex); // Jump to specific step
void SetStateByTag(FGameplayTag Tag); // Jump to first step matching tag

Blueprint NativeEvents​

void OnProxyInitialized(const FERPInstanceKey& Key);
// Called after spawn and key assignment. Override to configure StateSteps or custom setup.

void OnInstanceInteracted(AActor* InstigatorActor, int32 ActionIndex);
// Called on interaction. Default calls AdvanceState().
// Override to give loot, play VFX, etc.

void OnStateChanged(FGameplayTag OldState, FGameplayTag NewState, int32 StepIndex);
// Called on state transition. Default calls ApplyCurrentStep() (mesh + descriptor + timer).
// Call Parent to keep default behavior.

UERPInstanceSwapSubsystem​

World subsystem that tracks instanced interaction state globally. Persists instance states across World Partition stream in/out cycles and PCG regeneration with stable seeds. States are identified by GameplayTags (children of ERP.Instance).

Header: Domains/InstancedInteraction/ERPInstanceSwapSubsystem.h

Methods​

// Proxy management
AERPInstanceProxy* GetProxyForInstance(const FERPInstanceKey& Key) const;
bool RegisterProxy(const FERPInstanceKey& Key, AERPInstanceProxy* Proxy);
void UnregisterProxy(const FERPInstanceKey& Key);

// ISMC restore
void StoreISMCRestoreInfo(const FERPInstanceKey& Key, UInstancedStaticMeshComponent* ISMC,
const FTransform& OriginalTransform);
void RestoreISMCInstance(const FERPInstanceKey& Key);
void SwapISMCInstance(const FERPInstanceKey& Key, UStaticMesh* SwapMesh);
void DestroyDistantStandIn(const FERPInstanceKey& Key);

// State persistence
FGameplayTag GetInstanceState(const FERPInstanceKey& Key) const;
int32 GetInstanceStateIndex(const FERPInstanceKey& Key) const;
void SetInstanceState(const FERPInstanceKey& Key, FGameplayTag StateTag, int32 StepIndex);
bool HasPersistedState(const FERPInstanceKey& Key) const;
void PurgeStaleStates(float MaxAgeSeconds);
// Removes states older than MaxAgeSeconds that have no active proxy.

IERPInstanceStateReceiver​

Interface for actors that receive instance state notifications. Implement on any actor class (not just AERPInstanceProxy) to receive state callbacks from the instanced interaction system.

Header: Domains/InstancedInteraction/ERPInstanceStateReceiver.h

Methods (BlueprintNativeEvent)​

void OnInstanceStateInitialized(const FERPInstanceKey& Key, FGameplayTag StateTag,
int32 StepIndex, const TArray<FERPInstanceStateStep>& StateSteps);
// Called once after spawning with the instance key and initial state.
// Use to configure the actor based on which state it is replacing.

void OnInstanceStateChanged(FGameplayTag OldState, FGameplayTag NewState, int32 NewStepIndex);
// Called when the state changes (via timer auto-transition or external call).
// Override to play transition animations, swap meshes, spawn VFX, etc.

UStaticMesh* GetDistantMeshOverride() const;
// Return the mesh to show when this actor is despawned.
// Default: null (system falls back to StateStep.DistantMesh, then StateStep.Mesh).

FERPInstanceKey​

Stable key for identifying an ISMC/HISMC instance across World Partition stream in/out and PCG regeneration. Uses quantized position (cm precision) instead of instance index, because indices shift when instances are removed.

Header: Domains/InstancedInteraction/ERPInstanceTypes.h

FieldTypeDescription
OwnerPathFNameActor path of the ISMC owner (stable per WP cell)
QuantizedPosFIntVectorPosition quantized to centimeters for stable matching
FString ToString() const;
bool operator==(const FERPInstanceKey& Other) const;

FERPInstanceStateStep​

One step in an instance's state lifecycle. Configure an ordered array of these to define how an instance behaves.

Header: Domains/InstancedInteraction/ERPInstanceTypes.h

FieldTypeDefaultDescription
StateFGameplayTagTag identifying this state (e.g., ERP.Instance.Normal)
MeshUStaticMesh*nullMesh on the proxy actor. Null = hidden
DistantMeshUStaticMesh*nullMesh in the ISMC when the player leaves. Null = use Mesh
DescriptorFERPInteractionDescriptorInteraction descriptor. Empty Actions array = not interactable
Durationfloat0Seconds before auto-advancing to next step. 0 = wait for interaction
bLoopToFirstboolfalseIf last step and Duration expires, loop back to step 0

FERPInstancedMeshConfig​

DataTable row (inherits FTableRowBase) mapping a static mesh to its instanced interaction configuration.

Header: Domains/InstancedInteraction/ERPInstanceTypes.h

FieldTypeDescription
MeshTSoftObjectPtr<UStaticMesh>The ISMC mesh to match against
ProxyClassTSubclassOf<AActor>Actor class to spawn (AERPInstanceProxy or any actor implementing IERPInstanceStateReceiver)
StateStepsTArray<FERPInstanceStateStep>Ordered state lifecycle. Overrides proxy defaults if non-empty

See Instanced Interaction Guide for usage details and examples.


Next Steps​

See Quick Reference for common patterns.

Review Customization for extension examples.

Create custom domains with Custom Domains.