Destruction hit

Every field of FSDFDestructionHit, and why Damage and DestructionPower are two separate concepts.

FSDFDestructionHit is the only payload the framework needs from gameplay code. It carries no weapon class, no ability class and no combat framework assumption.

Fields

FieldTypeMeaning
DamagefloatConventional damage, applied to health after the profile’s threshold and multipliers
DestructionPowerESDFDestructionPowerDiscrete capability of the hit to break things
ImpactLocationFVectorWorld-space contact point
ImpactNormalFVectorSurface normal at the contact
ImpactDirectionFVectorDirection the source was travelling toward the target
ImpulseStrengthfloatPhysics impulse magnitude available to presentation
InstigatorAController*Controller responsible for the hit
DamageCauserAActor*Actor that caused it
DamageTypeTSubclassOf<UDamageType>Standard engine damage type, optional
GameplayTagsFGameplayTagContainerFree-form tags your systems can read back
PhysicalMaterialUPhysicalMaterial*Optional surface material at the contact
WeaponUObject*Generic optional source object; no weapon framework is required
RandomSeedint32-1 asks the receiving system to generate one
PropagationDepthuint8Chain depth; 0 means a root hit

Damage and DestructionPower are separate

This is the central design decision of the runtime layer, and the one most likely to surprise.

  • Damage answers how much health is removed.
  • DestructionPower answers whether this kind of hit is capable of breaking this kind of object at all.

ESDFDestructionPower is an ordered enumeration:

ValueNumeric
None0
VeryLight1
Light2
Medium3
Heavy4
Massive5

A profile declares MinimumDestructionPower. A hit below that value is rejected regardless of how much Damage it carries — a thousand points of arrow damage still does not topple a stone statue if the statue requires Heavy.

The converse also holds. With bDestroyOnSingleValidHit, a fragile pot breaks on the first hit that passes the power gate, even with very little damage. With bAllowPowerOverride and InstantBreakPower, a sufficiently powerful hit destroys the object regardless of remaining health.

Worked example

A ceramic pot: MinimumDestructionPower = VeryLight, bDestroyOnSingleValidHit = true. A roll contact carrying Damage = 0 and DestructionPower = Light destroys it. A wooden crate: MaxHealth = 100, MinimumDestructionPower = Light. The same roll only damages it, and it takes several hits to break.

Impact geometry

ImpactLocation, ImpactNormal and ImpactDirection have distinct jobs:

  • ImpactLocation positions debris, audio, VFX and decals.
  • ImpactNormal orients decals and any Niagara variation that opts into normal alignment.
  • ImpactDirection drives the directional component of debris impulse and of the Geometry Collection break velocity.

ImpactDirection points from the attacker toward the target. Supplying the reverse makes debris fly back toward the attacker.

Impulse

ImpulseStrength is a magnitude, not a vector. The profile decides how much of it is used: DirectionalImpulseWeight, RandomImpulseWeight and UpwardImpulseWeight for the debris path, and HitReactionImpulseMultiplier capped by MaximumHitReactionImpulse for non-breaking reactions.

The three hit sender components compute a bounded impulse for you from their own settings; when you build a hit by hand, you own that number.

Source references

Instigator, DamageCauser, DamageType, GameplayTags, PhysicalMaterial and Weapon are pure carry-through. SDF does not interpret them — it stores them in the hit, echoes them in results and requests, and lets your own listeners branch on them.

Common uses:

  • tag a hit as Attack.Heavy and read the tag in your audio delegate to select a bank;
  • pass the physical material to a middleware layer for surface-aware sound;
  • pass a spell object as Weapon and read it back in OnDestroyed to award resources.

Random seed

Every presentation decision that varies — sound variation, Niagara variation, decal variation, debris scatter, loot selection — is derived from a seed.

  • RandomSeed = -1 (INDEX_NONE) asks the receiving system to generate one.
  • Any other value makes the result repeatable: the same hit produces the same variation choices.

The resolved seed is reported in FSDFDestructionResult::RandomSeed, so you can log it and replay a specific presentation.

Propagation depth

PropagationDepth is 0 for a hit your gameplay code sends. Chain reactions increment it, and the subsystem uses it to enforce the maximum depth. Leave it at 0 unless you are building your own propagation logic. See Chain reactions.

Building a hit in Blueprint

  1. Add a Make SDF Destruction Hit node (FSDFDestructionHit is a Blueprint type).
  2. Set Damage and Destruction Power.
  3. Feed Impact Location and Impact Normal from your trace or overlap result.
  4. Compute Impact Direction — usually the normalised vector from attacker to target.
  5. Set Impulse Strength.
  6. Call Apply Destruction Damage on the target’s SDF Destructible component.

If your systems already produce hit results, prefer the matching hit sender component (melee, collision, projectile) — they build the payload and handle duplicate suppression for you.

Building a hit in C++

FSDFDestructionHit Hit;
Hit.Damage = 25.f;
Hit.DestructionPower = ESDFDestructionPower::Medium;
Hit.ImpactLocation = HitResult.ImpactPoint;
Hit.ImpactNormal = HitResult.ImpactNormal;
Hit.ImpactDirection = (Target->GetActorLocation() - Attacker->GetActorLocation()).GetSafeNormal();
Hit.ImpulseStrength = 500.f;
Hit.Instigator = AttackerController;
Hit.DamageCauser = Attacker;

const FSDFDestructionResult Result = DestructibleComponent->ApplyDestructionDamage(Hit);

Last updated: 2026-08-13

Type to search titles, sections and keywords.