Projectile integration
Data-driven projectile impacts with USDFProjectileHitSenderComponent and USDFProjectileHitProfile — arrows, bolts, thrown objects and magic, without an imposed projectile class.
USDFProjectileHitSenderComponent turns an impact your projectile already detected into a
destruction payload, using a data asset that describes what that projectile does.
No imposed projectile class
SDF does not require AProjectile, a specific movement component or a particular collision setup.
Any Actor — or any system that produces an FHitResult — can drive it.
Setup
- Add SDF Projectile Hit Sender to the projectile Actor.
- Assign a
USDFProjectileHitProfiledata asset toProjectileProfile. - On your existing impact event, call
Send SDF Projectile Hit. - For pooled projectiles, call
Reset SDF Projectile Impactswhen the projectile is reused.
The projectile profile
USDFProjectileHitProfile is a UPrimaryDataAsset. One asset per projectile type, reused by every
instance:
| Property | Default | Meaning |
|---|---|---|
Damage | 25.0 | Conventional damage |
DestructionPower | VeryLight | Capability gate |
ImpulseStrength | 300.0 | Base impulse before any speed contribution |
ImpulsePerSpeedUnit | 0.0 | Optional speed contribution to the impulse |
MaximumImpulseStrength | 1500.0 | Hard cap on the computed impulse |
DamageType | none | Optional engine damage type |
GameplayTags | empty | Tags carried to listeners |
bSuppressRepeatedActors | true | One Actor is impacted at most once by this sender |
Four demo profiles ship with the plugin under /SoulsDestructionFramework/Demo/ProjectileProfiles:
Arrow, CrossbowBolt, ThrownRock and MagicHeavy.
Arrow
Low damage, low destruction power, low impulse. An arrow should pin into a crate and destroy a
fragile pot, not shatter a barricade. Leave ImpulsePerSpeedUnit at 0 so a fast arrow does not
become a battering ram.
Crossbow bolt
Higher damage and impulse than an arrow, usually one power step above it, so bolts break what arrows only chip.
Thrown object
A rock or a jar. Moderate damage with a real speed contribution — set ImpulsePerSpeedUnit above
zero so a hard throw scatters debris further than a lob, while MaximumImpulseStrength keeps the top
end bounded.
Magic projectile
Whatever your spell system needs. A heavy magic bolt typically carries a high DestructionPower so
it breaks objects that resist physical projectiles. Pass the spell object as ProjectileObject and
read it back in your delegates.
Sending an impact
| Parameter | Notes |
|---|---|
TargetActor | Optional when HitResult contains an Actor |
HitResult | Supplies impact point and normal |
ProjectileVelocity | Drives impact direction and the optional speed contribution |
InstigatorController | Controller credited with the shot |
DamageCauser | Usually the projectile Actor |
ProjectileObject | Any UObject — the spell, the ammo definition, the weapon that fired |
RandomSeed | -1 to generate one |
Result: FSDFProjectileDeliveryResult — bDelivered, bSuppressedAsDuplicate,
bTargetSupportsDestruction, bMissingProfile, ProjectileSpeed, Target, SentHit and
DestructionResult.
bMissingProfile is the first thing to check when a projectile does nothing: no profile assigned
means no payload to build.
Object pooling
Pooled projectiles keep their component state between uses. ResetProjectileImpacts clears the
per-target impact history so a recycled arrow can hit the same crate on its next flight.
Call it when the projectile is taken from the pool, not when it is returned — that way a projectile that is destroyed rather than pooled needs no special handling.
SetProjectileProfile swaps the data asset at runtime, which suits a pool of generic projectiles
that changes identity per shot.
Blueprint example
Projectile OnHit / OnComponentHit
-> SDF Projectile Hit Sender -> Send SDF Projectile Hit
Target Actor = Other Actor
Hit Result = Hit
Projectile Velocity = Get Velocity
Instigator = Owner -> Get Controller
Damage Causer = self
Projectile Object = self
Random Seed = -1
-> Branch on Destruction Result -> b Destruction Triggered
True -> spawn a stronger impact effect
False -> spawn the default impact effect
C++ example
void AMyArrow::OnImpact(const FHitResult& HitResult)
{
const FSDFProjectileDeliveryResult Delivery = ProjectileSender->SendProjectileHit(
HitResult.GetActor(),
HitResult,
GetVelocity(),
GetInstigatorController(),
this,
this,
/* RandomSeed */ -1);
if (Delivery.bMissingProfile)
{
UE_LOG(LogTemp, Warning, TEXT("Arrow has no SDF projectile profile assigned"));
}
}
Choosing power values
A workable ladder for a souls-like, tuned against your own prop profiles:
| Projectile | Typical DestructionPower |
|---|---|
| Arrow | VeryLight |
| Crossbow bolt | Light |
| Thrown rock or jar | Light to Medium |
| Heavy magic bolt | Medium to Heavy |
The prop side of that contract is MinimumDestructionPower on each destruction profile. Keep the two
ladders written down together — they are one design decision, not two.
Last updated: 2026-08-13