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

  1. Add SDF Projectile Hit Sender to the projectile Actor.
  2. Assign a USDFProjectileHitProfile data asset to ProjectileProfile.
  3. On your existing impact event, call Send SDF Projectile Hit.
  4. For pooled projectiles, call Reset SDF Projectile Impacts when the projectile is reused.

The projectile profile

USDFProjectileHitProfile is a UPrimaryDataAsset. One asset per projectile type, reused by every instance:

PropertyDefaultMeaning
Damage25.0Conventional damage
DestructionPowerVeryLightCapability gate
ImpulseStrength300.0Base impulse before any speed contribution
ImpulsePerSpeedUnit0.0Optional speed contribution to the impulse
MaximumImpulseStrength1500.0Hard cap on the computed impulse
DamageTypenoneOptional engine damage type
GameplayTagsemptyTags carried to listeners
bSuppressRepeatedActorstrueOne 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

ParameterNotes
TargetActorOptional when HitResult contains an Actor
HitResultSupplies impact point and normal
ProjectileVelocityDrives impact direction and the optional speed contribution
InstigatorControllerController credited with the shot
DamageCauserUsually the projectile Actor
ProjectileObjectAny 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:

ProjectileTypical DestructionPower
ArrowVeryLight
Crossbow boltLight
Thrown rock or jarLight to Medium
Heavy magic boltMedium 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

Type to search titles, sections and keywords.