C++ API

Public C++ headers, types and signatures of the SoulsDestructionRuntime module, plus the editor-only authoring, regeneration and batch service facades.

Taken from the shipped public headers. Every symbol below exists in the plugin source; nothing is paraphrased into a name that does not compile.

Modules and headers

ModuleTypePublic headers
SoulsDestructionRuntimeRuntimeSDFDestructionTypes.h, SDFDestructibleComponent.h, SDFDestructibleActor.h, SDFPhysicsDestructibleActor.h, SDFGameplayTags.h, SDFDestructibleInterface.h, SDFDestructionProfile.h, SDFDestructionSubsystem.h, SDFDeveloperSettings.h, SDFMeleeTypes.h, SDFMeleeHitSenderComponent.h, SDFCollisionTypes.h, SDFCollisionHitSenderComponent.h, SDFProjectileTypes.h, SDFProjectileHitSenderComponent.h, SDFRadialTypes.h, SDFPropagationTypes.h, SDFAudioTypes.h, SDFVFXTypes.h, SDFDamagePresentationTypes.h, SDFLootTypes.h
SoulsDestructionEditorEditorSDFAuthoringTypes.h, SDFDestructionAuthoringPreset.h, SDFDestructionAuthoringService.h, SDFDestructionAuthoringSession.h, SDFDestructionAuthoringSettings.h, SDFDestructionAuthoringManifest.h, SDFDestructionRegenerationService.h, SDFDestructionBatchService.h, SDFDestructionBatchSession.h, SDFStaticMeshAnalyzer.h, SoulsDestructionEditorModule.h

The export macros are SOULSDESTRUCTIONRUNTIME_API and SOULSDESTRUCTIONEDITOR_API.

Never link the editor module from runtime code

SoulsDestructionRuntime has no dependency on SoulsDestructionEditor or UnrealEd, and that is verified in every phase audit. Adding the editor module to a runtime target will break packaging.

FSDFDestructionHit

USTRUCT(BlueprintType)
struct SOULSDESTRUCTIONRUNTIME_API FSDFDestructionHit
{
    float Damage = 0.0f;
    ESDFDestructionPower DestructionPower = ESDFDestructionPower::None;
    FVector ImpactLocation = FVector::ZeroVector;
    FVector ImpactNormal = FVector::ZeroVector;
    FVector ImpactDirection = FVector::ZeroVector;
    float ImpulseStrength = 0.0f;
    TObjectPtr<AController> Instigator = nullptr;
    TObjectPtr<AActor> DamageCauser = nullptr;
    TSubclassOf<UDamageType> DamageType;
    FGameplayTagContainer GameplayTags;
    TObjectPtr<UPhysicalMaterial> PhysicalMaterial = nullptr;
    TObjectPtr<UObject> Weapon = nullptr;
    int32 RandomSeed = INDEX_NONE;
    uint8 PropagationDepth = 0;
};

FSDFDestructionResult

USTRUCT(BlueprintType)
struct SOULSDESTRUCTIONRUNTIME_API FSDFDestructionResult
{
    ESDFDestructionOutcome Outcome = ESDFDestructionOutcome::Ignored;
    ESDFDestructionState PreviousState = ESDFDestructionState::Intact;
    ESDFDestructionState NewState = ESDFDestructionState::Intact;
    ESDFDestructionMode ModeUsed = ESDFDestructionMode::None;
    float AppliedDamage = 0.0f;
    float RemainingHealth = 0.0f;
    int32 RandomSeed = INDEX_NONE;
    int32 SpawnedDebrisCount = 0;
    bool bDestructionTriggered = false;
    bool bUsedFallback = false;
    bool bPresentationSuppressedByBudget = false;
};

USDFDestructibleComponent

UCLASS(BlueprintType, ClassGroup = (SoulsDestruction), meta = (BlueprintSpawnableComponent))
class SOULSDESTRUCTIONRUNTIME_API USDFDestructibleComponent : public UActorComponent
{
public:
    FSDFDestructionResult ApplyDestructionDamage(const FSDFDestructionHit& Hit);

    ESDFDestructionState GetDestructionState() const;
    USDFDestructionProfile* GetDestructionProfile() const;
    float GetCurrentHealth() const;
    int32 GetCurrentDamageStageIndex() const;
    int32 GetActiveImpactDecalCount() const;
    FSDFHitReactionRequest GetLastHitReactionRequest() const;
    FSDFDamageStageChange GetLastDamageStageChange() const;
    FSDFDecalRequest GetLastImpactDecalRequest() const;
    FSDFLootRequest GetLastLootRequest() const;
    int32 GetLootRequestCount() const;

    bool ResetDestruction();

    // Intact physics (UPROPERTY EditAnywhere, BlueprintReadOnly; read at BeginPlay)
    ESDFIntactPhysicsOverride PhysicsModeOverride = ESDFIntactPhysicsOverride::UseProfile;
    ESDFIntactPhysicsMode GetEffectivePhysicsMode() const;
    void SetPhysicsModeOverride(ESDFIntactPhysicsOverride NewOverride);
    ESDFIntactPhysicsStatus GetIntactPhysicsStatus() const;
    int32 GetLastSupportWakeCount() const;

    // Fall damage diagnostics
    float GetLastFallHeightCm() const;
    float GetLastFallDamage() const;

    void SetDestructionProfile(USDFDestructionProfile* NewProfile);
    void SetIntactComponent(UPrimitiveComponent* NewIntactComponent);
    void SetLootSpawnComponent(USceneComponent* NewLootSpawnComponent);
    void AddActorToReveal(AActor* ActorToReveal);
    void ClearActorsToReveal();

    bool RequestAudioEvent(
        ESDFAudioEvent Event,
        FVector Location,
        FVector ImpactDirection,
        float ImpactSpeed,
        ESDFDestructionPower DestructionPower,
        int32 RandomSeed);

    bool RequestVFXEvent(
        ESDFVFXEvent Event,
        FVector Location,
        FVector ImpactNormal,
        FVector ImpactDirection,
        float ImpactSpeed,
        ESDFDestructionPower DestructionPower,
        int32 RandomSeed,
        FName CustomName = NAME_None);

    static int32 SelectWeightedSoundVariation(
        const TArray<FSDFWeightedSound>& Variations,
        int32 RandomSeed,
        float& OutVolumeMultiplier,
        float& OutPitchMultiplier);

    static int32 SelectWeightedVFXVariation(
        const TArray<FSDFWeightedNiagaraSystem>& Variations,
        int32 RandomSeed,
        FVector& OutScale,
        FRotator& OutRotation,
        FVector ImpactNormal,
        FVector ImpactDirection);

    static int32 SelectWeightedDecalVariation(
        const TArray<FSDFWeightedDecal>& Variations,
        int32 RandomSeed,
        FVector ImpactNormal,
        FRotator& OutRotation);

    static int32 SelectWeightedLootEntry(
        const TArray<FSDFWeightedLootActor>& Entries,
        int32 RandomSeed);
};

Delegate types

DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FSDFDamageReceivedSignature, const FSDFDestructionHit&, Hit, const FSDFDestructionResult&, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FSDFStateChangedSignature, ESDFDestructionState, PreviousState, ESDFDestructionState, NewState);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FSDFDestructionEventSignature, const FSDFDestructionHit&, Hit, const FSDFDestructionResult&, Result);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSDFDebrisSpawnedSignature, AActor*, DebrisActor);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSDFAudioRequestedSignature, const FSDFDestructionAudioRequest&, Request);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSDFVFXRequestedSignature, const FSDFDestructionVFXRequest&, Request);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSDFHitReactionRequestedSignature, const FSDFHitReactionRequest&, Request);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSDFDamageStageChangedSignature, const FSDFDamageStageChange&, Change);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSDFDecalRequestedSignature, const FSDFDecalRequest&, Request);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FSDFLootRequestedSignature, const FSDFLootRequest&, Request);

Members: OnDestructionDamageReceived, OnDestructionStateChanged, OnDestructionStarted, OnDestroyed, OnDebrisSpawned, OnDestructionAudioRequested, OnDestructionVFXRequested, OnHitReactionRequested, OnDamageStageChanged, OnImpactDecalRequested, OnLootRequested.

The component can tick, but starts with its tick disabled. It enables it only while its profile has bEnableFallDamage set, to follow a falling intact body.

Intact physics types

From SDFDestructionTypes.h:

UENUM(BlueprintType)
enum class ESDFIntactPhysicsMode : uint8
{
    KeepExisting UMETA(DisplayName = "Keep Existing"), // profile class default
    Static       UMETA(DisplayName = "Static"),
    Simulated    UMETA(DisplayName = "Simulated")
};

UENUM(BlueprintType)
enum class ESDFIntactPhysicsOverride : uint8
{
    UseProfile,
    ForceStatic,
    ForceSimulated
};

UENUM(BlueprintType)
enum class ESDFIntactPhysicsStatus : uint8
{
    NotApplied,
    KeptExisting,
    AppliedStatic,
    AppliedSimulated,
    RefusedNoIntact,
    RefusedIntactNotRoot,
    RefusedMultipleDestructibles,
    RefusedNoSimpleCollision,
    RefusedComplexAsSimple,
    RefusedByPhysicsEngine
};

From SDFDestructionProfile.h (all EditDefaultsOnly, BlueprintReadOnly):

ESDFIntactPhysicsMode PhysicsMode = ESDFIntactPhysicsMode::KeepExisting;
bool bEnableFallDamage = false;
float MinimumFallHeightCm = 80.0f;      // centimetres
float FallDamagePerMeter = 50.0f;       // damage per metre beyond MinimumFallHeightCm
ESDFDestructionPower FallDestructionPower = ESDFDestructionPower::VeryLight;

UFUNCTION(BlueprintPure)
float ComputeFallDamage(float DropHeightCm) const; // max(0, (Drop - Minimum) * 0.01 * PerMeter), 0 when disabled

These are class defaults. New generations write per-family values — see Destruction profiles.

From SDFGameplayTags.h, the landing hit carries SDFGameplayTags::TAG_SDF_Source_Collision_Fall (SDF.Source.Collision.Fall).

ASDFPhysicsDestructibleActor

UCLASS(BlueprintType, Blueprintable)
class SOULSDESTRUCTIONRUNTIME_API ASDFPhysicsDestructibleActor : public ASDFDestructibleActor
{
public:
    ASDFPhysicsDestructibleActor();
    virtual void OnConstruction(const FTransform& Transform) override;
};

The intact Static Mesh is the root and the collider; the bounds box stays for API compatibility but collides with nothing. ASDFDestructibleActor additionally exposes bool PrepareIntactForSimulation() (C++ only, not a UFUNCTION): called by the destructible component when the classic Actor’s effective mode is Simulated, it makes the intact mesh the root in the running world, keeping every world transform. See Intact physics and fall damage.

USDFDestructionSubsystem

UCLASS()
class SOULSDESTRUCTIONRUNTIME_API USDFDestructionSubsystem : public UWorldSubsystem
{
public:
    void ConfigureBudgetLimits(const FSDFDestructionBudgetLimits& NewLimits);
    FSDFDestructionBudgetLimits GetBudgetLimits() const;
    FSDFDestructionBudgetStats GetBudgetStats() const;
    void ResetBudgetStatistics();
    int32 GetActiveDebrisCount() const;

    FSDFRadialDestructionResult ApplyRadialDestruction(const FSDFRadialDestructionRequest& Request);

    static float CalculateRadialFalloffMultiplier(
        float Distance,
        float Radius,
        ESDFRadialFalloff Falloff,
        float MinimumFalloffMultiplier = 0.0f);

    static int32 CalculateRadialTargetSeed(int32 AggregateSeed, int32 StableTargetIndex);
    static int32 CalculatePropagationSeed(int32 ParentSeed, uint8 SourceDepth, const AActor* SourceActor);

    FSDFPropagationChainResult GetLastPropagationChainResult() const;

    FSDFDestructionAudioStats GetAudioStats() const;
    FSDFDestructionAudioRequest GetLastAudioRequest() const;
    void ResetAudioStatistics();

    FSDFDestructionVFXStats GetVFXStats() const;
    FSDFDestructionVFXRequest GetLastVFXRequest() const;
    void ResetVFXStatistics();

    void RegisterDebris(AActor* DebrisActor, float LifetimeSeconds);
};

Delegates: OnPropagationChainCompleted, OnDestructionAudioRequested, OnDestructionVFXRequested.

Internal admission API

Budget admission and Chaos reservation (TryAdmitDestructionEvent, TryReserveChaosRepresentation and related) are private and reserved for the framework’s own backends. Gameplay code configures limits and reads diagnostics.

Hit sender components

// Melee
int32 BeginMeleeSwing(int32 RequestedSwingId = -1);
void EndMeleeSwing();
FSDFMeleeDeliveryResult SendMeleeHit(
    AActor* TargetActor,
    const FHitResult& HitResult,
    FVector AttackDirection,
    AController* InstigatorController,
    AActor* DamageCauser,
    UObject* Weapon,
    int32 RandomSeed = -1);
bool IsMeleeSwingActive() const;
int32 GetActiveSwingId() const;

// Collision
int32 BeginCollisionWindow(int32 RequestedWindowId = -1);
void EndCollisionWindow();
FSDFCollisionDeliveryResult SendCollisionHit(
    AActor* TargetActor,
    const FHitResult& HitResult,
    FVector SourceVelocity,
    float Damage,
    ESDFDestructionPower DestructionPower,
    AController* InstigatorController,
    AActor* DamageCauser,
    UObject* SourceObject,
    int32 RandomSeed = -1);
bool IsCollisionWindowActive() const;
int32 GetActiveCollisionWindowId() const;

// Projectile
void ResetProjectileImpacts();
FSDFProjectileDeliveryResult SendProjectileHit(
    AActor* TargetActor,
    const FHitResult& HitResult,
    FVector ProjectileVelocity,
    AController* InstigatorController,
    AActor* DamageCauser,
    UObject* ProjectileObject,
    int32 RandomSeed = -1);
void SetProjectileProfile(USDFProjectileHitProfile* NewProfile);
USDFProjectileHitProfile* GetProjectileProfile() const;

Delegates: OnMeleeHitDelivered, OnCollisionHitDelivered, OnProjectileHitDelivered.

ISDFDestructibleInterface

UINTERFACE(BlueprintType)
class SOULSDESTRUCTIONRUNTIME_API USDFDestructibleInterface : public UInterface { };

class SOULSDESTRUCTIONRUNTIME_API ISDFDestructibleInterface
{
public:
    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Souls Destruction|Damage")
    bool CanReceiveDestructionHit(const FSDFDestructionHit& Hit) const;

    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Souls Destruction|Damage")
    FSDFDestructionResult ReceiveDestructionHit(const FSDFDestructionHit& Hit);

    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Souls Destruction|State")
    bool CanDestroyFromHit(const FSDFDestructionHit& Hit) const;

    UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Souls Destruction|State")
    ESDFDestructionState GetDestructionState() const;
};

ASDFDestructibleActor implements all four through CanReceiveDestructionHit_Implementation, ReceiveDestructionHit_Implementation, CanDestroyFromHit_Implementation and GetDestructionState_Implementation.

ASDFGlassCompositeActor

A prop assembled from one structural frame and any number of independent glass panels, built entirely from data. The authoring pipeline splits a single multi-material Static Mesh into these pieces; this Actor turns them back into a working composite at spawn.

UCLASS(BlueprintType)
class SOULSDESTRUCTIONRUNTIME_API ASDFGlassCompositeActor : public AActor
{
public:
    UFUNCTION(BlueprintPure, Category = "Souls Destruction|Composite")
    int32 GetPanelCount() const;

    UFUNCTION(BlueprintPure, Category = "Souls Destruction|Composite")
    UStaticMeshComponent* GetPanelComponent(int32 Index) const;

    UFUNCTION(BlueprintPure, Category = "Souls Destruction|Composite")
    USDFDestructibleComponent* GetPanelDestructible(int32 Index) const;

    UFUNCTION(BlueprintPure, Category = "Souls Destruction|Composite")
    UStaticMeshComponent* GetFrameComponent() const;

    UStaticMesh* GetFrameMesh() const;
    const TArray<TObjectPtr<UStaticMesh>>& GetPanelMeshes() const;
    USDFDestructionProfile* GetPanelProfile() const;
};

Editable data properties: FrameMesh (never breakable), PanelMeshes (one Static Mesh per pane) and PanelProfile (the Glass runtime-fracture profile shared by every pane). The frame deliberately receives no destructible component: a primitive nothing owns is structurally immune. See Runtime glass fracture.

FSDFGlassFractureSettings

The runtime glass tuning struct carried by USDFDestructionProfile::GlassSettings when DestructionMode is Glass. Pattern (ImpactRadius, RadialCrackCount, RingCount, ShardCountMin/Max, PositionJitter, AngleJitter, RandomSeedOverride), shard thickness (GlassThickness, bPreserveSourceThickness, MinimumMeasurableThickness), physics (ImpulseStrength, RadialImpulseBias, NormalImpulseBias, DirectionNoise, NearImpactImpulseMultiplier, AngularVelocityMin/Max) and cleanup (bPersistentShards, ShardLifetimeMin/Max). Every property is BlueprintReadWrite. Full reference: Runtime glass fracture.

USDFDeveloperSettings

UCLASS(Config = Game, DefaultConfig, meta = (DisplayName = "Souls Destruction Framework"))
class SOULSDESTRUCTIONRUNTIME_API USDFDeveloperSettings : public UDeveloperSettings
{
public:
    UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category = "Performance Budget")
    FSDFDestructionBudgetLimits BudgetLimits;
};

Category Plugins, section Souls Destruction Framework.

Editor-only services

Available to editor modules and automation only.

class SOULSDESTRUCTIONEDITOR_API FSDFStaticMeshAnalyzer final
{
public:
    static FSDFStaticMeshAnalysis Analyze(
        const UStaticMesh* SourceMesh,
        const USDFDestructionAuthoringPreset* Preset,
        const USDFDestructionAuthoringSettings* Settings);

    static FSDFResolvedAuthoringPlan BuildPlan(
        const UStaticMesh* SourceMesh,
        const FSDFStaticMeshAnalysis& Analysis,
        const USDFDestructionAuthoringPreset* Preset,
        const USDFDestructionAuthoringSettings* Settings,
        ESDFAuthoringDestructionMode RequestedMode,
        ESDFAuthoringFractureDensity Density,
        int32 CustomFragmentCount,
        ESDFOutputFolderPolicy OutputPolicy,
        const FString& CustomOutputFolder,
        bool bCreateActor);

    static FString MakeBaseAssetName(const UStaticMesh* SourceMesh);
    static FString ResolveOutputFolder(
        const UStaticMesh* SourceMesh,
        const USDFDestructionAuthoringSettings* Settings,
        ESDFOutputFolderPolicy Policy,
        const FString& CustomOutputFolder);
};

class SOULSDESTRUCTIONEDITOR_API FSDFDestructionAuthoringService
{
public:
    static FSDFStaticMeshSourceSignature CaptureSourceSignature(const UStaticMesh* SourceMesh);
    static FSDFValidationReport Generate(const FSDFDestructionAuthoringRequest& Request);
    static FSDFValidationReport ValidateGeneratedSetup(
        const FSDFDestructionAuthoringRequest& Request,
        UGeometryCollection* GeometryCollection,
        UObject* DestructionProfile,
        UObject* DestructibleActor,
        const FSDFStaticMeshSourceSignature& BeforeSignature);
};

class SOULSDESTRUCTIONEDITOR_API FSDFDestructionRegenerationService
{
public:
    static constexpr int32 CurrentManifestSchemaVersion = 4;

    static FSDFAssetFingerprint CaptureFingerprint(const FSoftObjectPath& ObjectPath);
    static FSDFDestructionSetupValidationReport Validate(const USDFDestructionAuthoringManifest* Manifest);
    static bool UpgradeLegacyManifestOwnership(
        USDFDestructionAuthoringManifest* Manifest,
        USDFDestructionAuthoringPreset* Preset,
        bool bExplicitlyConfirmed,
        TArray<FSDFValidationIssue>* OutIssues = nullptr);
    static FSDFRegenerationReport Regenerate(const FSDFRegenerationRequest& Request);
    static bool StampCurrentOwnership(USDFDestructionAuthoringManifest* Manifest, bool bSaveManifest);
};

class SOULSDESTRUCTIONEDITOR_API FSDFDestructionBatchService
{
public:
    using FShouldCancel = TFunction<bool()>;
    using FProgress = TFunction<void(int32 Completed, int32 Total, const UStaticMesh* Current, const FText& Stage)>;

    static FSDFBatchReport Preflight(const FSDFBatchRequest& Request);
    static FSDFBatchReport Execute(
        const FSDFBatchRequest& Request,
        const FSDFBatchReport& ApprovedPreflight,
        FShouldCancel ShouldCancel = {},
        FProgress Progress = {});
    static bool ExportReportCsv(FSDFBatchReport& Report, const FString& OptionalAbsolutePath = FString());
};

FSDFDestructionAuthoringRequest and FSDFBatchRequest carry PhysicsMode, bPhysicsPolicyAuthored and bGenerateSimulationCollisionIfNeeded. On a batch request left with bPhysicsPolicyAuthored = false, each preset family’s default applies (Simulated); the physics fields participate in the batch request signature. The authoring manifest records bPhysicsPolicyRecorded, PhysicsMode, bGenerateSimulationCollisionIfNeeded, SimulationMesh and SimulationMeshFingerprint.

The editor module also registers the console command SDF.MigrateToSimulatedPhysics [VerifyOnly] [Root=/Game/Path] [Exit]. It is an editor tool, not a runtime or Blueprint API — see Migrating older setups.

FSDFDestructionAuthoringRequest and the manifest also carry WoodLengthCuts (-1 = the preset’s own rule, 0 – FSDFDestructionAuthoringRequest::MaxWoodLengthCuts, which is 5) and PieceCollisionShape (ESDFPieceCollisionShape, honoured when USDFDestructionAuthoringPreset::OffersPieceCollisionShape() is true — Wooden Furniture). The editor command SDF.ModifyDestructible <Asset> [Preset=] [Density=] [Fragments=] [Cuts=] [Collision=] [Fragile=] [MaxHealth=] [ReplaceManual] [Exit] rebuilds an existing setup with new choices — see Modify Destructible.

Editor enumerations

EnumValues
ESDFAuthoringPresetFamilyWood, Ceramic, Stone, Generic, Custom, Glass, GlassVessel
ESDFAuthoringDestructionModeAutomatic, GeometryCollection, SwapAndScatter, CustomAuthoredDebris
ESDFAuthoringFractureDensityLow, Medium, High, Custom
ESDFOutputFolderPolicySourceSiblingGenerated, ProjectDefault, Custom
ESDFPieceCollisionShapeBoxes, Convex
ESDFValidationSeverityPass, Warning, Error
ESDFAuthoringDriftKindNone, LegacyManifest, SourceChanged, PresetChanged, InteriorMaterialChanged, GeometryCollectionChanged, RuntimeProfileChanged, DestructibleActorChanged, OutputMissing, ReferenceMismatch, UnsavedChanges
ESDFBatchOperationGenerate, Validate, Regenerate
ESDFBatchItemStatusReady, Warning, Blocked, Running, Success, Failed, Skipped, Cancelled

Build integration

// MyGame.Build.cs
PublicDependencyModuleNames.AddRange(new string[]
{
    "Core",
    "CoreUObject",
    "Engine",
    "GameplayTags",
    "SoulsDestructionRuntime"
});

Minimal integration example

#include "SDFDestructibleComponent.h"
#include "SDFDestructionTypes.h"

void AMyWeapon::OnBladeContact(const FHitResult& HitResult)
{
    AActor* Target = HitResult.GetActor();
    if (Target == nullptr)
    {
        return;
    }

    USDFDestructibleComponent* Destructible =
        Target->FindComponentByClass<USDFDestructibleComponent>();
    if (Destructible == nullptr)
    {
        return;
    }

    FSDFDestructionHit Hit;
    Hit.Damage = 40.f;
    Hit.DestructionPower = ESDFDestructionPower::Heavy;
    Hit.ImpactLocation = HitResult.ImpactPoint;
    Hit.ImpactNormal = HitResult.ImpactNormal;
    Hit.ImpactDirection = (Target->GetActorLocation() - GetActorLocation()).GetSafeNormal();
    Hit.ImpulseStrength = 800.f;
    Hit.Instigator = GetInstigatorController();
    Hit.DamageCauser = this;

    const FSDFDestructionResult Result = Destructible->ApplyDestructionDamage(Hit);
    if (Result.Outcome == ESDFDestructionOutcome::Destroyed)
    {
        // Award resources, trigger hit stop, spawn a reward...
    }
}

Last updated: 2026-10-01

Type to search titles, sections and keywords.