Chain reactions
Opt-in bounded propagation — how a destroyed object can damage its neighbours, with depth caps, cycle prevention and deterministic ordering.
Propagation lets a destroyed object deliver a bounded radial hit to nearby destructibles. It is disabled by default on every profile.
Heavy Prop
↓
Crate
↙ ↘
Pot Pot
Enabling it
On the profile of the object that should start a chain when it dies:
| Property | Default | Meaning |
|---|---|---|
bAllowDestructionPropagation | false | Master switch |
PropagationRadius | 250.0 | Sphere radius searched for neighbours |
PropagationDamage | 100.0 | Damage delivered to each neighbour |
PropagationPower | Light | Destruction power of the propagated hit |
PropagationImpulse | 600.0 | Impulse magnitude of the propagated hit |
MaxPropagationDepth | 2 | Hard depth cap when this profile starts a chain |
Depth is capped by the root
MaxPropagationDepth is the hard maximum for the chain that this profile started. A child profile
encountered later in the chain may reduce the remaining depth, but it can never increase it. One
explosive barrel cannot be turned into an unbounded chain by a neighbour with a larger setting.
What a propagated hit looks like
Each neighbour receives a normal FSDFDestructionHit:
Damage= the source profile’sPropagationDamage;DestructionPower=PropagationPower;ImpulseStrength=PropagationImpulse;ImpactDirection= outward, from the source toward the neighbour;PropagationDepth= parent depth + 1;RandomSeed= derived deterministically (see below).
The neighbour evaluates it against its own profile like any other hit. A pot with
MinimumDestructionPower = VeryLight breaks; a statue requiring Heavy ignores a Light
propagation.
Cycle prevention
The subsystem keeps a visited set of Actors for the duration of a logical chain. An Actor that has
already been visited is never queued again, so A → B → A is impossible. The number of such
suppressions is reported as TargetsIgnoredAlreadyVisited.
The chain is processed as a queue, not as recursion, which keeps the call stack flat regardless of how many objects are involved.
Deterministic ordering and seeds
Candidates are gathered and placed in a stable order before any hit is delivered, so the same scene produces the same chain every run.
CalculatePropagationSeed(ParentSeed, SourceDepth, SourceActor) derives each event’s seed from its
parent seed and stable source context. Given the same root seed, a chain replays identically — useful
for capturing a bug, and for deterministic automated tests.
Chain diagnostics
When a chain completes, OnPropagationChainCompleted broadcasts an FSDFPropagationChainResult.
GetLastPropagationChainResult returns the same data on demand.
| Field | Meaning |
|---|---|
bExecuted | A chain actually ran |
RootActor | The object that started it |
RootSeed | Seed the chain was derived from |
TargetsDiscovered | Compatible neighbours found |
HitsPropagated | Hits actually delivered |
DestroyedTargets | Neighbours destroyed by the chain |
MaximumDepthReached | Deepest level reached |
TargetsIgnoredAlreadyVisited | Suppressed by the visited set |
TargetsIgnoredByMaximumDepth | Neighbours skipped because the cap was reached |
SourcesBlockedByMaximumDepth | Sources that could not propagate further |
UniqueActorsVisited | Size of the visited set |
HitResults | Per-hit records: source, target, depth, seed, destruction result |
Each FSDFPropagationHitResult contains the full FSDFDestructionResult of that target, so a chain
can be audited hit by hit.
Budgets still apply
Propagated destruction is normal destruction. It competes for the same per-frame destruction event
admission and the same Chaos representation budget as player-caused destruction, and it falls back to
SwapAndScatter under pressure exactly the same way. A chain in a crowded scene degrades instead of
spiking. See Performance.
Tuning guidance
- Start with
PropagationRadiusslightly larger than the visual footprint of the source object. A radius that reaches across a corridor turns one crate into a room-wide cascade. - Give the chain a lower
PropagationPowerthan the player’s heavy attack. Chains that break everything read as a bug rather than as a reaction. - Keep
MaxPropagationDepthat2unless you are building an intentional set piece. - Use the chain result counters while tuning: a high
TargetsIgnoredByMaximumDepthmeans the layout wants a smaller radius, not a bigger cap.
Radial versus propagation
They deliver similar payloads but are triggered differently:
| Radial | Propagation | |
|---|---|---|
| Trigger | Your gameplay code calls ApplyRadialDestruction | An object with propagation enabled is destroyed |
| Configuration | Per call, in the request | On the source object’s profile |
| Depth | You set PropagationDepth on the request | Managed by the chain |
| Result | FSDFRadialDestructionResult | FSDFPropagationChainResult |
See Radial destruction.
Last updated: 2026-08-13