Core Concepts
This page explains how ElysImpact’s pipeline works end-to-end, from calling PlayResponse to each handler completing.
The Pipeline
PlayResponse(Asset, Context)
│
▼
UERP_ImpactSubsystem::CreateSession
│
├─ Channel filter (muted? → drop)
├─ Feel Profile suppression check
├─ Combined intensity computation
│ ContextOverride × AssetMultiplier × GlobalScale × ChannelScale × DI curve
├─ Choreography role assignment
├─ Dramatic Intensity accumulation
│
▼
UERP_ImpactSession::Start
│
└─ For each Handler (concurrent):
├─ Pre-conditions (enabled? ExecutionChance? distance? tags?)
├─ StartDelay timer
└─ Handler::Play_Internal
Response Assets
UERP_ImpactResponseAsset is a UDataAsset. Open it in the editor to configure:
| Property | Description |
|---|---|
Handlers | List of inline handlers (EditInlineNew — configured directly in the asset) |
IntensityMultiplier | Scales the combined intensity for all handlers in this asset |
Channels | GameplayTag set — used for muting and per-channel intensity |
DramaticContribution | How much this response contributes to the target’s DI accumulator |
ChoreographyGroup | Tag-based area-response role system (see Choreography below) |
Creating a Response Asset
- Content Browser → right-click → Miscellaneous → Data Asset →
UERP_ImpactResponseAsset - Add handlers via the
+button in theHandlersarray - Expand each handler to configure its properties
Handlers
A handler is an EditInlineNew UObject that performs exactly one effect. Handlers run concurrently within a session — a Camera Shake and a Sound Effect in the same asset both start at the same time (subject to their individual StartDelay).
Common Handler Properties
All handlers share these base properties (on the UERP_ImpactHandler base class):
| Property | Description |
|---|---|
bEnabled | Toggle without removing the handler |
ExecutionChance | Probability [0..1] that this handler fires on any given play |
StartDelay | Seconds to wait before playing (within the session) |
IntensityScale | Per-handler intensity multiplier |
IntensityRandomRange | Adds random [-Range, +Range] to final intensity |
IntensityOverLifetime | Optional curve: scales intensity over the handler’s duration |
MaxPlayDistance | Beyond this distance from the camera, the handler is silenced |
LODDistanceFade | Distance at which intensity starts fading |
TargetTagRequirement | Handler only fires if target has these GameplayTags |
SourceTagRequirement | Handler only fires if source has these GameplayTags |
bQuantizeToBeat | Defers play to the next ElysMusicEngine beat division |
BeatDivision | Which beat division to quantize to |
Session Isolation
When a session is created, each handler template from the asset is duplicated (DuplicateObject) so concurrent sessions never share mutable state. You can play the same asset on 10 actors simultaneously — each gets its own handler instances.
Intensity
The final intensity passed to each handler is:
CombinedIntensity = Context.IntensityOverride
× Asset.IntensityMultiplier
× Subsystem.GlobalIntensity
× ChannelIntensity (lowest among asset’s channels)
× DICurve(NormalizedDI)
× FeelProfile.GlobalIntensityScale
After choreography role assignment:
Secondaryrole:× ChoreographyGroup.SecondaryIntensityScaleTertiaryrole:× ChoreographyGroup.TertiaryIntensityScale
Each handler then applies its own IntensityScale and curve on top.
Impact Context
FERP_ImpactContext carries rich event data through the pipeline:
| Field | Type | Description |
|---|---|---|
Target | TWeakObjectPtr<AActor> | Actor receiving the response (required) |
Source | TWeakObjectPtr<AActor> | Actor triggering the response (optional) |
Instigator | TWeakObjectPtr<AController> | Controller responsible (optional) |
EventTag | FGameplayTag | Semantic label (e.g., Impact.Hit.Heavy) |
Magnitude | float | Raw value (damage, force…) — affects DI accumulation |
ImpactPoint | FVector | World position of the impact |
ImpactNormal | FVector | Surface normal at impact |
IntensityOverride | float | Per-call intensity multiplier (default 1.0) |
bSkipReplication | bool | If true, skip network propagation |
Build a context manually or use the helper functions:
// Minimal
FERP_ImpactContext Context = UERP_ImpactStatics::MakeImpactContext(TargetActor, 1.f);
// From a hit result
FERP_ImpactContext Context = UERP_ImpactStatics::MakeImpactContextFromHit(HitResult, Damage);
Dramatic Intensity
The DI system makes repeated responses feel progressively more impactful:
- Each
PlayResponsecall accumulates DI on the target actor:CurrentDI += Magnitude × Asset.DramaticContribution - DI decays over time (exponential decay driven by
DecayRate) - Normalized DI
[0..1]is fed through the Feel Profile’sDramaticIntensityCurve - The curve output multiplies the combined intensity
Default behavior (no Feel Profile): linear scale from 1× at DI=0 to 2× at DI=1.
Read and reset DI from Blueprint:
Get Dramatic Intensity → (WorldContext, Actor) → float [0..1]
Reset Dramatic Intensity → (WorldContext, Actor)
Choreography
When many actors are hit simultaneously, Choreography prevents visual overload by assigning roles:
- Primary: Full intensity — the most important response (usually the player’s target)
- Secondary: Reduced intensity (
SecondaryIntensityScale, default 0.6) - Tertiary: Minimal intensity (
TertiaryIntensityScale, default 0.3)
Configure on the Response Asset’s ChoreographyGroup:
| Property | Description |
|---|---|
GroupTag | Unique tag identifying this choreography group |
PrimaryLockDuration | Seconds before another actor can claim the Primary role |
MaxSecondaryCount | Max concurrent Secondary responses |
SecondaryIntensityScale | Intensity multiplier for Secondary |
TertiaryIntensityScale | Intensity multiplier for Tertiary |
Set the same GroupTag on all response assets that should compete for roles within an area.
Sessions
A UERP_ImpactSession is a UObject that:
- Owns the duplicated handler instances
- Tracks handler completion
- Fires
OnCompletewhen all handlers finish - Is removed from
ActiveSessionson the next subsystem tick
Sessions are GC-managed — they live as long as the subsystem holds a reference. You rarely need to interact with sessions directly.
To stop a session early:
UERP_ImpactStatics::StopSession(this, Session);
UERP_ImpactStatics::StopAllOnActor(this, TargetActor);
Next Steps
Browse Handler Reference for all available effects.
Configure intensity scaling in Feel Profiles.
Organize your responses with Channels.