Melee integration
Wire an existing melee combat system to SDF with USDFMeleeHitSenderComponent — swing windows, one hit per target per swing, and explicit delivery results.
USDFMeleeHitSenderComponent is an optional bridge between a melee contact your game already
detected and an SDF destructible. It detects nothing itself.
Who owns what
Your game owns weapon traces, overlaps, animation notifies and what counts as a swing. SDF owns turning an accepted contact into a destruction payload, suppressing duplicates and reporting what happened.
Setup
- Add SDF Melee Hit Sender to the Actor that swings — usually the character, sometimes the weapon Actor.
- Configure
HitSettings. - Call
Begin SDF Melee Swingwhen the damage window opens. - Call
Send SDF Melee Hitfor each contact your trace detects. - Call
End SDF Melee Swingwhen the window closes.
No timer and no tick are used. The swing window is explicit state.
Hit settings
FSDFMeleeHitSettings:
| Property | Default | Meaning |
|---|---|---|
Damage | 25.0 | Conventional damage written into the payload |
DestructionPower | Light | Capability gate of the swing |
ImpulseStrength | 500.0 | Impulse magnitude written into the payload |
DamageType | none | Optional engine damage type |
GameplayTags | empty | Tags carried through to listeners |
bRequireActiveSwing | true | Delivery is allowed only between Begin and End |
bSuppressRepeatedActorsPerSwing | true | One Actor receives at most one hit per swing |
Different attacks need different values: set HitSettings from your attack data just before
Begin SDF Melee Swing, or use several sender components.
The swing concept
Begin Swing -> opens the window, clears per-target history, returns a stable swing id
Submit Contact -> Send SDF Melee Hit, once per detected contact
-> at most one delivery per Actor for this swing
End Swing -> closes the window
Next swing -> history is reset again
Begin SDF Melee Swing accepts an optional requested id and returns the active swing id.
Is Melee Swing Active and Get Active Swing Id expose the current state.
This matters because a multi-trace weapon typically reports the same crate three or four times in one animation. Without suppression, a crate with 100 health would take 75 damage instead of 25 from a single swing.
Sending a contact
Send SDF Melee Hit takes:
| Parameter | Notes |
|---|---|
TargetActor | Optional when HitResult already contains an Actor |
HitResult | Your trace or overlap result; supplies impact point and normal |
AttackDirection | Points from the attacker toward the target |
InstigatorController | Controller credited with the hit |
DamageCauser | Usually the character or the weapon Actor |
Weapon | Any UObject; SDF does not interpret it |
RandomSeed | -1 to generate one |
It returns FSDFMeleeDeliveryResult:
| Field | Meaning |
|---|---|
bDelivered | The hit reached a destructible |
bSuppressedAsDuplicate | Same Actor, same swing |
bRejectedBecauseSwingInactive | No swing window was open |
bTargetSupportsDestruction | The target implements the destructible contract |
Target | The Actor that was addressed |
SentHit | The exact payload that was built |
DestructionResult | The target’s own evaluation |
Two separate answers
Delivery and destruction are different questions. bDelivered says the payload arrived;
DestructionResult.Outcome says what the object decided to do with it. A Rejected outcome on a
delivered hit means the object’s power gate refused the swing.
Non-destructible targets
Hitting a wall, an enemy or anything that does not implement the destructible contract is safe: the
result reports bTargetSupportsDestruction = false and nothing else happens. You do not need to
filter your traces before calling.
Blueprint example
Inside your character Blueprint:
AnimNotify: DamageWindowStart
-> SDF Melee Hit Sender -> Begin SDF Melee Swing
Weapon trace produced a Hit Result
-> SDF Melee Hit Sender -> Send SDF Melee Hit
Target Actor = Hit Result -> Hit Actor
Hit Result = Hit Result
Attack Direction = normalize(Target Location - Attacker Location)
Instigator = Get Controller
Damage Causer = self
Weapon = EquippedWeapon
Random Seed = -1
-> break the returned result to log or react
AnimNotify: DamageWindowEnd
-> SDF Melee Hit Sender -> End SDF Melee Swing
C++ example
// Damage window opens
MeleeSender->BeginMeleeSwing();
// For each detected contact
const FVector AttackDirection =
(HitResult.GetActor()->GetActorLocation() - GetActorLocation()).GetSafeNormal();
const FSDFMeleeDeliveryResult Delivery = MeleeSender->SendMeleeHit(
HitResult.GetActor(),
HitResult,
AttackDirection,
GetController(),
this,
EquippedWeapon,
/* RandomSeed */ -1);
if (Delivery.DestructionResult.bDestructionTriggered)
{
// React: hit stop, camera shake, resource award...
}
// Damage window closes
MeleeSender->EndMeleeSwing();
Listening to deliveries
OnMeleeHitDelivered broadcasts the full FSDFMeleeDeliveryResult for every call, which is a
convenient single place to drive hit stop, controller rumble or combat log entries without wiring
them at every call site.
Common mistakes
| Symptom | Cause |
|---|---|
Nothing breaks, bRejectedBecauseSwingInactive is true | Begin SDF Melee Swing was never called, or End fired too early |
| One swing removes several times the expected damage | bSuppressRepeatedActorsPerSwing was disabled |
| Debris flies toward the attacker | AttackDirection is reversed |
Delivered but Outcome is Rejected | The swing’s DestructionPower is below the profile’s MinimumDestructionPower |
Last updated: 2026-08-13