Skip to main content

Instanced Interaction

Turn thousands of identical ISMC instances (trees, rocks, bushes) into individually interactable objects with state — without placing a single actor by hand.

What It Does

Your level has an ISMC with 500 pine trees. You want each tree to be harvestable: the player walks up, presses [E], the tree becomes a stump, then regrows after 30 seconds. The Instanced Interaction system handles this automatically:

  • When the player gets close, the ISMC instance is seamlessly replaced by a real actor
  • The actor can be interacted with, change state, play VFX, give loot
  • When the player walks away, the actor is cleaned up and the mesh returns to the ISMC
  • State is remembered — if the player comes back, the tree is still a stump

Works with World Partition, PCG, and the rest of ElysAwareness out of the box.


Quick Start

1. Create a DataTable

Content Browser → Right-click → Miscellaneous → DataTable → Row Structure: ERPInstancedMeshConfig

Add a row for each mesh you want to make interactable:

Row NameMeshProxyClassStateSteps
PineTreeSM_Pine_1BP_TreeProxy(see step 4)

2. Create a Proxy Blueprint

Content Browser → Blueprint Class → Parent: ERPInstanceProxy

Name it BP_TreeProxy. It comes with a StaticMeshComponent and an ERPInteractableComponent built in — the system sets them automatically from the current state.

3. Add the Component

On your PlayerController or Pawn, add an ERPInstancedInteractionComponent:

PropertyValueWhy
MeshConfigTableYour DataTableLinks meshes to proxy actors
SwapRadius600How close (cm) the player must be to activate an instance
DespawnMargin200Extra range before cleanup — prevents flickering at the edge
tip

Set SwapRadius larger than your awareness DefaultSamplingRange. The proxy actor must exist before perception can detect it for interaction prompts.

4. Configure State Steps

In the DataTable row (or on the proxy Blueprint defaults), set up the StateSteps array — each entry is one state in the lifecycle:

Example: Harvestable tree

#State TagMeshDistant MeshDescriptorDurationLoop to First
0ERP.Instance.NormalSM_Pine_1(empty)"Pine Tree" — [E] Harvest0false
1ERP.Instance.HarvestedSM_StumpSM_Stump(no actions)30false
2ERP.Instance.RegrowingSM_SaplingSM_Sapling(no actions)60true

What each field does:

  • State Tag: GameplayTag identifying this state (for queries and persistence)
  • Mesh: What the proxy actor shows when the player is nearby
  • Distant Mesh: What shows in the distance when the player walks away. Leave empty to use the regular Mesh. Set to a different mesh to show a stump, rubble, etc. from afar
  • Descriptor: The interaction prompt. Empty Actions = not interactable in this state
  • Duration: 0 = stays until interaction. > 0 = auto-advances to the next step after this many seconds
  • Loop to First: On the last step only — when its Duration expires, loop back to step 0

5. Play

Walk near your ISMC trees. They become interactable proxies with the prompt you configured. Interact, watch the state change, walk away, come back — it all works.


Customizing the Proxy

Override these events in your proxy Blueprint to add gameplay logic:

OnInstanceInteracted

Called when the player interacts. Default behavior: advance to the next state.

Event OnInstanceInteracted (InstigatorActor, ActionIndex)
-> Spawn Emitter: VFX_TreeChop
-> Play Sound: SFX_Chop
-> Add Item to Inventory: "Wood" x5
-> Call Parent // advances state (Normal → Harvested)

OnStateChanged

Called on every state transition. Default behavior: applies mesh + descriptor from the step. Call Parent to keep this, then add your own logic:

Event OnStateChanged (OldState, NewState, StepIndex)
-> Call Parent
-> If NewState == ERP.Instance.Normal
-> Spawn Emitter: VFX_TreeRegrow

OnProxyInitialized

Called once at spawn. Use it to configure the proxy dynamically:

Event OnProxyInitialized (Key)
-> Set State Steps from DataTable lookup
-> Configure widget classes

State Control

From anywhere in the proxy Blueprint:

MethodDescription
AdvanceState()Go to the next step (loops if last step has Loop to First)
SetStateByIndex(Index)Jump to a specific step
SetStateByTag(Tag)Jump to the first step matching this tag
GetCurrentStateTag()Get the current state GameplayTag
IsInteractable()True if the current step has actions

Using Any Actor (Not Just Proxies)

You're not limited to ERPInstanceProxy. Set any Blueprint class as the ProxyClass in the DataTable — an animated character, a Niagara effect, a skeletal mesh with physics.

Receiving State Notifications

Implement the IERPInstanceStateReceiver interface on your actor to receive state callbacks:

Event OnInstanceStateInitialized (Key, StateTag, StepIndex, StateSteps)
-> Switch on StateTag
-> Normal: Set skeletal mesh pose "Idle"
-> Destroyed: Set skeletal mesh pose "Crumbled"

Event OnInstanceStateChanged (OldState, NewState, NewStepIndex)
-> Play transition animation

Function GetDistantMeshOverride -> Return: SM_CustomDistantMesh
CallbackWhenUse For
OnInstanceStateInitializedAt spawnConfigure visuals based on initial state
OnInstanceStateChangedOn state transitionsPlay animations, swap meshes, spawn VFX
GetDistantMeshOverrideAt despawnReturn a mesh to show from a distance

The component manages timers and state transitions for generic actors — your actor just receives notifications and reacts.

note

Generic actors don't have a built-in ERPInteractableComponent. Add one to your Blueprint if you need interaction prompts.


Listening to State Changes (Player Side)

The ERPInstancedInteractionComponent on the player has a delegate that fires for all instance actors (proxy or generic):

Bind Event to OnInstanceActorStateChanged
-> If StateTag == ERP.Instance.Harvested
-> Add to Inventory: "Wood x5"
-> Update Quest: "Chop 5 Trees"
-> Play Sound: SFX_TreeFall

Use this for player-side logic that shouldn't live in the proxy (inventory, quests, UI updates).


Tips

  • GameplayTags: Create tags under ERP.Instance (e.g., ERP.Instance.Normal, ERP.Instance.Harvested). They're used for state identification and queries.
  • State persists: If the player walks away during "Harvested" and comes back 10 seconds later, the proxy respawns at "Harvested" with the remaining timer intact.
  • PCG compatible: Works with PCG-generated ISMCs as long as seeds are stable (positions don't shift between regenerations).
  • Performance: ScanInterval controls how often the system checks for instances. The default 0.2s (5 Hz) is fine for most games. Increase for better performance with very large instance counts.

Troubleshooting

ProblemFix
No proxies spawnCheck that MeshConfigTable is assigned and rows have both Mesh and ProxyClass set
No interaction promptThe current step's Descriptor needs at least one Action with an InputAction
Flickering at boundaryIncrease DespawnMargin (default 200 cm)
Wrong state after returningEnsure PCG uses stable seeds so positions are consistent
Distant mesh not showingSet DistantMesh on the state step, or return one from GetDistantMeshOverride()

Next Steps

Set up regular interactions with Interaction Guide.

See all API details in API Reference.