Damage stages
Optional pre-destruction appearance stages driven by remaining health ratio, with mesh replacement and per-slot material overrides.
Damage stages let an object visibly deteriorate before it breaks.
Intact
↓
Damaged 1
↓
Damaged 2
↓
Destroyed
They are optional and disabled by default: an empty DamageStages array means an object goes
straight from intact to destroyed.
Defining a stage
Each FSDFDamageStage in the profile’s DamageStages array:
| Property | Default | Meaning |
|---|---|---|
HealthRatioThreshold | 0.5 | The stage activates when the remaining health ratio is at or below this value (0–1) |
StaticMesh | none | Optional replacement mesh; empty keeps the mesh currently displayed |
MaterialOverrides | empty | Optional per-slot replacements; empty or null entries preserve their existing slots |
StageName | none | Optional semantic identifier for your own presentation logic |
Thresholds are evaluated by value
Stages are matched by their threshold value, not by their position in the array. Listing a 0.3
stage before a 0.66 stage does not change behaviour. Array order is not gameplay-significant.
For a crate with MaxHealth = 100:
Stage A: HealthRatioThreshold = 0.66 -> activates at 66 health
Stage B: HealthRatioThreshold = 0.33 -> activates at 33 health
Stage skipping
A single heavy hit can cross several thresholds at once. The component evaluates the current health
ratio and applies the appropriate stage directly — it does not step through the intermediate ones.
A crate at full health taking 80 damage jumps straight to the 0.33 stage.
No regression
Within one damage lifecycle, the stage index never moves backwards. A healing or repair system that restores health does not visually un-break the object; the appearance stays at the worst stage reached until the object is reset.
Why no regression
Regressing a stage would require reverting mesh and material overrides that other systems may have changed in the meantime. The framework keeps the lifecycle monotonic and leaves repair semantics to the game.
Mesh replacement
When a stage carries a StaticMesh, the intact component’s mesh is swapped for it. The reference is
soft, so the damaged meshes are loaded on demand rather than pinned by the profile.
Leaving StaticMesh empty is normal: many props only need material changes.
Material overrides
MaterialOverrides is per-slot and index-aligned with the intact component’s material slots. A null
or empty entry preserves the material already assigned to that slot, so you can change slot 1 without
restating slot 0.
Typical use: swap the base material for a variant with cracks, soot or exposed interior.
Stage change events
Every transition broadcasts OnDamageStageChanged with an FSDFDamageStageChange:
| Field | Meaning |
|---|---|
SourceActor | The object that changed stage |
PreviousStageIndex | Index before the change (-1 when there was none) |
NewStageIndex | Index after the change |
StageName | The stage’s semantic name, when set |
RemainingHealthRatio | Health ratio at the moment of the change |
bMeshApplied | Whether a replacement mesh was applied |
MaterialOverridesApplied | How many slots were overridden |
GetCurrentDamageStageIndex and GetLastDamageStageChange expose the same information on demand.
Use the event to layer your own presentation — a dust puff, a creak, a UI hint — without adding any per-object Blueprint logic to the framework.
Choosing thresholds
| Object | Suggested stages |
|---|---|
| Crate, barrel | Two stages at 0.66 and 0.33 |
| Statue, pillar | One stage at 0.5, since heavy props rarely survive long enough for more |
| Fragile pot | None — a pot that breaks on the first valid hit never reaches a stage |
Stages cost an asset each. Two well-read stages beat four subtle ones.
Damage stages versus destruction
Damage stages are pure presentation on the intact representation. They do not change health, resistance or the power gate, and they never destroy the object. Destruction is decided entirely by the rules in Destruction profiles.
Last updated: 2026-08-13