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 Name | Mesh | ProxyClass | StateSteps |
|---|---|---|---|
| PineTree | SM_Pine_1 | BP_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:
| Property | Value | Why |
|---|---|---|
| MeshConfigTable | Your DataTable | Links meshes to proxy actors |
| SwapRadius | 600 | How close (cm) the player must be to activate an instance |
| DespawnMargin | 200 | Extra range before cleanup — prevents flickering at the edge |
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 Tag | Mesh | Distant Mesh | Descriptor | Duration | Loop to First |
|---|---|---|---|---|---|---|
| 0 | ERP.Instance.Normal | SM_Pine_1 | (empty) | "Pine Tree" — [E] Harvest | 0 | false |
| 1 | ERP.Instance.Harvested | SM_Stump | SM_Stump | (no actions) | 30 | false |
| 2 | ERP.Instance.Regrowing | SM_Sapling | SM_Sapling | (no actions) | 60 | true |
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:
| Method | Description |
|---|---|
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
| Callback | When | Use For |
|---|---|---|
OnInstanceStateInitialized | At spawn | Configure visuals based on initial state |
OnInstanceStateChanged | On state transitions | Play animations, swap meshes, spawn VFX |
GetDistantMeshOverride | At despawn | Return a mesh to show from a distance |
The component manages timers and state transitions for generic actors — your actor just receives notifications and reacts.
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:
ScanIntervalcontrols 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
| Problem | Fix |
|---|---|
| No proxies spawn | Check that MeshConfigTable is assigned and rows have both Mesh and ProxyClass set |
| No interaction prompt | The current step's Descriptor needs at least one Action with an InputAction |
| Flickering at boundary | Increase DespawnMargin (default 200 cm) |
| Wrong state after returning | Ensure PCG uses stable seeds so positions are consistent |
| Distant mesh not showing | Set 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.