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
| Property | Type | Default | Description |
|---|---|---|---|
PerceptionTickInterval | float | 0.0 | Tick interval in seconds (0 = every frame) |
DefaultSamplingRange | float | 2000.0 | Default sampling range (cm) passed to samplers |
ChannelPipelines | TArray<FERPChannelPipeline> | Multi-channel pipeline configuration | |
bProvideViewportInfoWhenAvailable | bool | false | Include viewport size and screen reference in context |
DefaultScreenReferenceNdc | FVector2D | (0.5, 0.5) | Default screen reference (normalized 0..1) |
bEvaluateOnlyForLocalController | bool | true | Only tick for the local player (multiplayer) |
bDebugPerception | bool | false | Enable debug logging |
DebugPerceptionIntervalSeconds | float | 0.0 | Debug 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.
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
| Property | Type | Default | Description |
|---|---|---|---|
PerceptionComponent | UERPAwarenessComponent* | nullptr | Auto-found on owner at BeginPlay |
ChannelId | FName | None | Perception 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)
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
| Property | Type | Default | Description |
|---|---|---|---|
Rules | TArray<UERPInteractionRule*> | Instanced validation rules | |
MaxInteractionDistance | float | 500.0 | Server-side distance validation (cm) |
Methods
// State
void GetCurrentDescriptor(FERPInteractionDescriptor& OutDescriptor) const;
bool HasDescriptor() 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), ignoresTriggeredAction - 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
UERPInteractableComponenton 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
| Property | Type | Default | Description |
|---|---|---|---|
Rules | TArray<UERPTargetRule*> | Instanced validation rules |
Methods
const FERPTargetDescriptor& GetCurrentDescriptor() const;
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
| Property | Type | Description |
|---|---|---|
DefaultDescriptor | FERPInteractionDescriptor | Used when BuildDescriptor is not bound |
CanInteractCheck | FERPCanInteractCheckDelegate | Runtime override for CanBeInteractedWith |
BuildDescriptor | FERPBuildDescriptorDelegate | Runtime override for descriptor |
Properties — Widget Classes
| Property | Type | Description |
|---|---|---|
SingleActionWidgetClass | TSubclassOf<UERPInteractionWidgetBase> | 1 action |
MultiActionWidgetClass | TSubclassOf<UERPInteractionWidgetBase> | 2+ actions, DirectKeys |
WheelWidgetClass | TSubclassOf<UERPInteractionWidgetBase> | 2+ actions, Wheel |
AmbientWidgetClass | TSubclassOf<UERPInteractionWidgetBase> | Always-on world marker (optional) |
WidgetClassOverride | TSubclassOf<UERPInteractionWidgetBase> | Overrides all of the above |
Properties — Placement
| Property | Type | Default | Description |
|---|---|---|---|
WidgetOffset | FVector | (0,0,0) | Offset from attachment point |
WidgetAnchorTag | FName | ERP_WidgetAnchor | Component tag for custom anchor |
WidgetSpace | EWidgetSpace | Screen | Screen or World space |
Properties — Feedback
| Property | Type | Default | Description |
|---|---|---|---|
bEnableCustomDepthFeedback | bool | true | Outline on focus |
CustomDepthStencilValue | int32 | 1 | Stencil 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
| Property | Type | Default | Description |
|---|---|---|---|
ChannelIds | TArray<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
| Class | Header | Parent | Description |
|---|---|---|---|
UERPBaseMultiPressChallengeWidget | UI/Interaction/ERPBaseMultiPressChallengeWidget.h | UERPChallengeWidgetBase | "Mash [E]" press counter with progress bar |
UERPBaseRadialHoldWidget | UI/Interaction/ERPBaseRadialHoldWidget.h | UERPChallengeWidgetBase | Circular fill hold challenge (MID-driven) |
UERPBaseWorldInteractionWidget | UI/Interaction/ERPBaseWorldInteractionWidget.h | UERPInteractionWidgetBase | World-space prompt for interactable actors |
UERPBaseTimedPressChallengeWidget | UI/Interaction/ERPBaseTimedPressChallengeWidget.h | UERPChallengeWidgetBase | Countdown bar + key prompt (QTE timed press) |
UERPBaseTimingChallengeWidget | UI/Interaction/ERPBaseTimingChallengeWidget.h | UERPChallengeWidgetBase | Track with moving cursor + target zone (QTE timing) |
Concrete Targeting Widgets
| Class | Header | Parent | Description |
|---|---|---|---|
UERPBaseTargetFrameWidget | UI/Targeting/ERPBaseTargetFrameWidget.h | UERPTargetingWidgetBase | HUD nameplate (name + icon + tag coloring) |
UERPBaseTargetHealthBarWidget | UI/Targeting/ERPBaseTargetHealthBarWidget.h | UERPBaseTargetFrameWidget | Nameplate + health bar |
UERPBaseTargetReticleWidget | UI/Targeting/ERPBaseTargetReticleWidget.h | UERPTargetingWidgetBase | World-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.
Methods (BlueprintNativeEvent)
void StartChallenge(); // Called when the attempt begins
void OnInputPressed(); // Called when the action input is pressed
void OnInputReleased(); // Called when the action input is released
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)
UERPHoldChallenge
Hold the action key for a fixed duration.
Header: Domains/Interaction/Challenges/ERPHoldChallenge.h
Properties
| Property | Type | Default | Description |
|---|---|---|---|
HoldDuration | float | 1.5 | Hold time in seconds |
Behavior:
StartChallenge: begins accumulating timeOnInputReleased: resets accumulated time, firesOnProgress(0)TickChallenge: advances progress; firesOnComplete(true)when duration reached
UERPMultiPressChallenge
Press the action key N times.
Header: Domains/Interaction/Challenges/ERPMultiPressChallenge.h
Properties
| Property | Type | Default | Description |
|---|---|---|---|
RequiredPresses | int32 | 5 | Number of presses to complete |
PressCooldown | float | 0.0 | Minimum time between valid presses (seconds) — useful for animation sync |
DecayPerSecond | float | 0.0 | Progress lost per second when not pressing — creates mash decay pressure |
Behavior:
OnInputPressed: increments press count (if cooldown elapsed), firesOnProgress; firesOnComplete(true)when count reachedTickChallenge: appliesDecayPerSecond(reduces progress toward 0 if not pressing)
UERPTimedPressChallenge
Press the action key before a countdown expires.
Header: Domains/Interaction/Challenges/ERPTimedPressChallenge.h
Properties
| Property | Type | Default | Description |
|---|---|---|---|
TimeWindow | float | 3.0 | Seconds before the challenge fails |
Behavior:
StartChallenge: begins countdown timerOnInputPressed: if timer hasn't expired, firesOnComplete(true)TickChallenge: advances timer; firesOnProgresswith value counting down from 1 to 0; firesOnComplete(false)on timeout
UERPSequenceChallenge
Press a series of input actions in the correct order.
Header: Domains/Interaction/Challenges/ERPSequenceChallenge.h
Properties
| Property | Type | Default | Description |
|---|---|---|---|
Sequence | TArray<UInputAction*> | Ordered list of input actions to press | |
bFailOnWrongKey | bool | true | Fail immediately on wrong key press |
TimeLimit | float | 0.0 | Max 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.
Behavior:
OnInputPressed: checks if the pressed action matchesSequence[CurrentIndex]; advances on match, fails on mismatch ifbFailOnWrongKeyTickChallenge: checksTimeLimit(if > 0); firesOnComplete(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
| Property | Type | Default | Description |
|---|---|---|---|
CursorSpeed | float | 1.0 | Cursor oscillation speed (cycles per second) |
TargetCenter | float | 0.5 | Center of the target zone (0..1) |
TargetHalfWidth | float | 0.1 | Half-width of the target zone |
bFailOnMiss | bool | false | Fail immediately if the player presses outside the zone |
RequiredHits | int32 | 1 | Successful hits needed to complete |
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 1OnInputPressed: checks if cursor is in target zone; increments hit count on success, fails on miss ifbFailOnMiss- Progress = current hits / required hits
- Fires
OnComplete(true)whenRequiredHitsreached
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 overlap query (spatial, range-limited)
- 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
- UERPGameplayTagFilter — Gameplay tag matching
Scorers
- UERPDistanceScorer — Distance-based (lower = closer = better)
- UERPConeScorer — Angle from forward direction
- UERPDotProductScorer — Dot product scoring
- UERPViewportEllipseScorer — Screen-space ellipse (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
| Property | Type | Default | Description |
|---|---|---|---|
MeshConfigTable | UDataTable* | null | DataTable (row type: FERPInstancedMeshConfig) defining which meshes are interactable |
SwapRadius | float | 600.0 | Radius (cm) around the owning pawn to scan for instances |
DespawnMargin | float | 200.0 | Extra margin added to SwapRadius for despawning (prevents flickering at boundary) |
ScanInterval | float | 0.2 | How 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
| Component | Type | Description |
|---|---|---|
MeshComponent | UStaticMeshComponent* | Root component. Mesh set automatically per state step |
InteractableComponent | UERPInteractableComponent* | Handles interaction focus, widget display, and descriptor |
Properties
| Property | Type | Default | Description |
|---|---|---|---|
StateSteps | TArray<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
| Field | Type | Description |
|---|---|---|
OwnerPath | FName | Actor path of the ISMC owner (stable per WP cell) |
QuantizedPos | FIntVector | Position 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
| Field | Type | Default | Description |
|---|---|---|---|
State | FGameplayTag | Tag identifying this state (e.g., ERP.Instance.Normal) | |
Mesh | UStaticMesh* | null | Mesh on the proxy actor. Null = hidden |
DistantMesh | UStaticMesh* | null | Mesh in the ISMC when the player leaves. Null = use Mesh |
Descriptor | FERPInteractionDescriptor | Interaction descriptor. Empty Actions array = not interactable | |
Duration | float | 0 | Seconds before auto-advancing to next step. 0 = wait for interaction |
bLoopToFirst | bool | false | If 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
| Field | Type | Description |
|---|---|---|
Mesh | TSoftObjectPtr<UStaticMesh> | The ISMC mesh to match against |
ProxyClass | TSubclassOf<AActor> | Actor class to spawn (AERPInstanceProxy or any actor implementing IERPInstanceStateReceiver) |
StateSteps | TArray<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.