Performance
World budgets for Chaos representations and destruction events, the Swap-and-Scatter fallback, cleanup lifecycle, the cost of simulated intact props and fall tracking, and how to size all of it for real scenes.
Destruction is the system most likely to spike a frame at the worst possible moment. SDF treats bounded behaviour as a feature rather than as tuning advice: every expensive path has an explicit cap and a defined degradation.
Budget limits
FSDFDestructionBudgetLimits is set project-wide under
Project Settings → Plugins → Souls Destruction Framework, and can be overridden per world at
runtime with ConfigureBudgetLimits.
| Limit | Default | Bounds |
|---|---|---|
MaxActiveChaosRepresentations | 24 | Simultaneously active Chaos Geometry Collection representations in the world |
MaxDestructionEventsPerFrame | 32 | Destruction events admitted in a single frame |
MaxBuiltInAudioEventsPerFrame | 32 | Built-in Unreal audio playback attempts per frame |
MaxBuiltInVFXEventsPerFrame | 64 | Built-in Niagara spawn attempts per frame |
MaxSettledDebrisActors | 60 | Frozen, persistent debris actors kept in the world. Persistent debris survives until a reset, so without a cap a long session accumulates presentation actors indefinitely. The oldest frozen debris is evicted first; zero disables eviction entirely |
Audio and VFX caps bound the built-in path only
Requests always reach the delegates. Only the framework’s own playback and spawning are throttled, so a middleware or pooled-VFX integration is never starved by these two numbers.
Chaos representation budget
The most expensive resource is an active Geometry Collection simulation. Before activating one, the
subsystem tries to reserve a slot against MaxActiveChaosRepresentations.
If no slot is available:
- with
bFallbackToSwapAndScatterenabled on the profile, the object destroys itself through the lightweight debris path and the result reportsbUsedFallback = true; - with the fallback disabled, no Chaos representation is created.
Either way the gameplay outcome is identical: the object is destroyed, the state machine advances, loot and events fire. Only the visual fidelity degrades.
The reservation is released when the representation is cleaned up, which returns the slot to the pool.
Per-frame event budget
MaxDestructionEventsPerFrame bounds how many destruction presentations start in one frame. When the
budget is exhausted, gameplay destruction still succeeds, but visual debris is suppressed and the
result reports bPresentationSuppressedByBudget = true.
That distinction is deliberate: a radial blast that destroys forty crates must not drop or delay the destruction of any of them, but it also must not spawn forty simulations in one tick.
Fallback path
Profile requests GeometryCollection
↓
Reserve a Chaos representation
↓ (unavailable)
bFallbackToSwapAndScatter = true
↓
Hide intact mesh, spawn bounded debris meshes
↓
Result: bUsedFallback = true
Give every GeometryCollection profile a usable Debris array, even if you expect the fallback to
be rare. A fallback with no debris entries destroys the object with no visual payoff at all.
Cleanup lifecycle
Debris and Chaos representations are registered with the subsystem for centralised, timer-driven
cleanup, based on the profile’s DebrisLifetime. There is no per-Actor cleanup timer and no cleanup
tick.
GetActiveDebrisCount reports how many tracked debris Actors currently exist.
Tick and physics at rest
The architecture stays mostly event-driven, but it is not free per frame, and it does not claim to be.
| Part | Per-frame behaviour |
|---|---|
ASDFDestructibleActor, ASDFPhysicsDestructibleActor | Actor tick disabled |
| Melee, collision and projectile hit senders | Component tick disabled; swing and collision windows are explicit state |
| Debris cleanup | Centralised and timer-driven in the world subsystem |
USDFDestructibleComponent | Tick disabled by default. Enabled only while its profile turns on fall damage, to follow a falling intact body; stopped when a destruction hides the intact, re-armed by a reset |
A Simulated intact prop | A Chaos rigid body: it costs physics-scene time even asleep, and more while awake |
| Active Geometry Collection debris | Chaos simulation, bounded by the budgets above |
Three different states, three different costs:
- At rest — a simulated prop that sleeps still occupies the physics scene. The plugin’s
SDF.Perf.IntactPhysics.RestingBodiesCostautomation test measured 100 sleepingSimulatedprops at 0.0283 ms per physics step against 0.0177 ms for the same 100 props heldStatic(median of 240 physics frames; AMD Ryzen 9 9950X, UE 5.8.2, headless test world). It times the physics scene step alone — not a full game frame, not awake bodies, not the fall-tracking tick. Treat it as an order of magnitude and run the test on your own hardware. - Woken — when a support breaks, the bodies resting on it wake and simulate until they settle again. A falling stack costs more than a sleeping one.
- Fall tracking — only profiles with fall damage enabled tick, and the tick does almost nothing while the intact is not simulating.
Props that never need to move are cheaper as Static. See
Intact physics and fall damage.
Diagnostics
GetBudgetStats returns FSDFDestructionBudgetStats:
| Field | Meaning |
|---|---|
ActiveChaosRepresentations | Slots currently in use |
ActiveTrackedDebrisActors | Debris Actors awaiting cleanup |
EventsAdmittedThisFrame | Destruction events admitted this frame |
EventsDeniedThisFrame | Events whose presentation was denied this frame |
TotalEventsAdmitted | Lifetime counter |
TotalEventsDenied | Lifetime counter |
TotalChaosRepresentationsAdmitted | Lifetime counter |
TotalChaosBudgetFallbacks | Times the fallback path was taken because of the budget |
ResetBudgetStatistics clears the counters while preserving active state, which makes it usable
between measured runs.
A rising TotalChaosBudgetFallbacks during normal play is the clearest signal that
MaxActiveChaosRepresentations is too low for the scene — or that DebrisLifetime is too long and
slots are not being returned fast enough.
Sizing guidance
The right numbers depend on your target platform, prop density and fragment counts. The defaults are a conservative starting point. Three scenarios, expressed as method rather than as benchmark numbers:
Small encounter — a corridor with a few pots
Defaults are already generous. Nothing needs changing. Watch EventsDeniedThisFrame: it should stay
at zero.
Medium room — a storeroom with crates, pots and barricades
Destruction is frequent but spread over time. Keep the Chaos cap at the default and shorten
DebrisLifetime on common props so slots return quickly. Verify with GetBudgetStats that
ActiveChaosRepresentations peaks below the cap.
Large destruction event — a scripted collapse or a heavy radial blast
Many objects are destroyed in one or two frames. Expect bPresentationSuppressedByBudget and
bUsedFallback on some targets — that is the system working. If the moment is a set piece and the
visual matters, raise MaxDestructionEventsPerFrame and MaxActiveChaosRepresentations for that
level with ConfigureBudgetLimits, then restore the defaults afterwards.
No frame-time figures are published for these budgets
GreyFox Studio does not publish frame-time figures for these budgets. They depend on your fragment
counts, materials, platform and scene. The only published measurement is the narrow resting-body
physics step above. Measure with Unreal Insights in your own project, using GetBudgetStats to
correlate spikes with admissions and fallbacks.
Authoring levers that dominate runtime cost
Runtime budgets bound the damage; authoring decisions determine how expensive each object is in the first place.
| Lever | Effect |
|---|---|
| Fracture density | The single strongest factor. Low on common props, High only for hero objects |
| Minimum fragment size | Larger minimums mean fewer tiny bodies and fewer contacts |
MaximumDebrisPieces | Directly bounds the fallback and Swap-and-Scatter cost |
DebrisLifetime | Shorter lifetimes return Chaos slots and reduce concurrent bodies |
MaximumImpactDecals | Cheap per decal, expensive across thirty props |
PhysicsMode | Static for props that never move; Simulated only where falling matters |
bEnableFallDamage | Adds a component tick per enabled prop; keep it on props whose landing should break them |
See Authoring presets.
Last updated: 2026-09-15