Skip to content
CRUSHFORMV1.1.0
GET IT ON FAB

WORLDIMPACT FEEDBACK

Impact feedback

When a car hits a wall, a fence, a tree or a window, it makes a sound and a spark. When a breakable piece lands, it makes a thud. Impact feedback is the part of Crushform that plays these. It turns a hit into an impact event, looks up what that event should sound and look like, and plays it at the place of the hit.

With the LogHits console variable on, the plugin reports every hit it judges. In the editor’s play session each hit leaves a marker for 5 seconds: a sphere at the point of impact with an arrow along the surface normal. It is green when the impact plays, yellow for a hit within a steady contact, and red for a hit below the minimum. Each judged hit also writes one line to the log, in the category LogCrushformImpact, in this form:

<owner>: <component> (bone <bone>) hit by <actor> / <component>, impulse N, support N, mass N kg, other mass N kg, normal Z N, intensity N at <point>: <verdict>

The verdict is played, below minimum or steady contact, suppressed.

Every impact is a gameplay tag, such as Crushform.Impact.Prop.Break.Wood, played at a location. The UCFImpactFeedbackSubsystem does the rest:

  1. It finds the row for the tag in the active impact set. If the set has no row for that exact tag, it uses the row of the closest parent tag that has one. If no row matches, nothing plays.
  2. It plays one sound from the row at random, and spawns the row’s Niagara effect with its Intensity parameter set.
  3. It scales the volume between the row’s Volume by Intensity values and picks a pitch from its Pitch Range.
  4. It applies the row’s filters: a hit below Min Intensity plays nothing, a source that played recently waits out its Cooldown Seconds, and while Max Concurrent Voices of the row are busy, a new impact plays its effect but no sound. Across the whole plugin, at most Max Sounds Per Frame sounds (2 by default) start in one frame: the rest wait, strongest first, for later frames, and a sound still waiting after Sound Queue Seconds (0.15 s) is dropped. Starting the sounds of a crash that makes many at once in one frame would cost a hitch, so they are spread over a few frames instead. Effects are never queued.

The impact set is a UCFImpactFeedbackSet data asset. The project’s default is /Crushform/Impact/DA_CF_ImpactFeedback, with a row for each of the plugin’s tags. A project can make its own set and point the Default Set at it.

Impacts come from components that sit on a body. You add them in the Blueprint editor’s Add menu, where all three are listed under Custom, not under Crushform:

  • UCFImpactFeedbackComponent reports the hits of the primitive it observes, with the Event Tag it is given (Crushform.Impact.Hit by default). It observes nothing until you give it a primitive with SetObservedPrimitive, which is C++ only. A hit is judged by its impulse per kilogram of the body. Below Min Impulse Per Kg (50) it is silent, and it is at full strength at Impulse Per Kg for Full Intensity (600). A steady contact, such as a body resting on the ground, does not repeat the impact.
  • UCFNetImpactFeedbackComponent observes its owner’s root primitive by itself, and it also relays a hit to the other players. A relay normally waits at least Min Relay Interval Seconds (0.5 s), and comes sooner for a markedly stronger hit.
  • UCFPartImpactFeedbackComponent plays the slam of a hinged part when it reaches an end of its travel. A part that slams shut into the closed end plays Slam Event Tag, Crushform.Impact.Part.Slam by default. A part flung wide into the open end plays Open Slam Event Tag, Crushform.Impact.Part.Slam.Open by default, and an impact set without a row for that tag plays the Part.Slam row.

A vehicle gets these from its adapter. A breakable definition names its own tags, and an empty one plays the plugin’s default.

The plugin declares 19 impact tags, in CFImpactTags:

TagPlayed when
Crushform.ImpactThe root of the impact events.
Crushform.Impact.HitA body with an impact feedback component hits something.
Crushform.Impact.Vehicle.CrashA vehicle’s body strikes something solid.
Crushform.Impact.Prop.BreakA breakable prop that is not glass breaks.
Crushform.Impact.Prop.Break.WoodA wooden prop breaks apart, such as a wooden fence section.
Crushform.Impact.Prop.Break.MetalA metal prop breaks off whole, such as a chain-link fence panel.
Crushform.Impact.Prop.DebrisA debris piece of a breakable prop hits something.
Crushform.Impact.Prop.Debris.WoodA wooden debris piece lands.
Crushform.Impact.Prop.Debris.MetalA metal debris piece lands.
Crushform.Impact.Glass.CrackA glass pane cracks.
Crushform.Impact.Glass.BreakA glass pane breaks and falls apart.
Crushform.Impact.Glass.ShardA glass shard hits something.
Crushform.Impact.Tree.HitA body pushes a breakable tree.
Crushform.Impact.Tree.BreakA breakable tree snaps and starts to fall.
Crushform.Impact.Tree.BendA breakable pole gives way and stays leaning.
Crushform.Impact.Tree.LandA fallen tree trunk hits the ground.
Crushform.Impact.Part.HitA vehicle’s part that swings on its hinge, or came off, hits something.
Crushform.Impact.Part.SlamA vehicle’s part swinging on its hinge slams into the closed end of its travel.
Crushform.Impact.Part.Slam.OpenA vehicle’s part swinging on its hinge, flung wide, slams into the open end of its travel.

The set’s row for a tag is a FCFImpactFeedbackEntry. Its Sounds are a list, one of which plays at random, so you need no sound cue for variation. Its Effect is a Niagara system that receives the float parameter Intensity. Its Attenuation shapes the sound over distance.

This uses the shipped set, and then makes a row of your own.

  1. In the Content Browser, the default set is in Plugins › Crushform Content › Impact.
  2. Open DA_CF_ImpactFeedback. Its Entries list has one row per tag. Find the row for Crushform.Impact.Prop.Break.Wood to see what a row holds: Sounds, Effect, Attenuation, the volume and pitch ranges, and the filters.
Impact
Entries18 Array elements
Index [ 0 ]Crushform.Impact.Prop.Break
Index [ 1 ]Crushform.Impact.Prop.Debris
Index [ 2 ]Crushform.Impact.Glass.Crack
Index [ 3 ]Crushform.Impact.Glass.Break
Index [ 4 ]Crushform.Impact.Glass.Shard
Index [ 5 ]Crushform.Impact.Vehicle.Crash
Index [ 6 ]Crushform.Impact.Hit
Index [ 7 ]Crushform.Impact.Tree.Hit
Index [ 8 ]Crushform.Impact.Tree.Break
Index [ 9 ]Crushform.Impact.Tree.Bend
Index [ 10 ]Crushform.Impact.Tree.Land
Index [ 11 ]Crushform.Impact.Prop.Break.Wood
Event TagCrushform.Impact.Prop.Break.Wood
Sounds5 Array elements
EffectNS_CF_ImpactWood_Break
AttenuationSA_CF_CarImpact
Volume by Intensity0.41.0
Pitch Range0.921.08
Min Intensity0.05
Cooldown Seconds0.1
Max Concurrent Voices4
Surface Overrides0 Array element
Index [ 12 ]Crushform.Impact.Prop.Debris.Wood
Index [ 13 ]Crushform.Impact.Prop.Break.Metal
Index [ 14 ]Crushform.Impact.Prop.Debris.Metal
Index [ 15 ]Crushform.Impact.Part.Hit
Index [ 16 ]Crushform.Impact.Part.Slam
Index [ 17 ]Crushform.Impact.Part.Slam.Open
The Entries of DA_CF_ImpactFeedback, with the Crushform.Impact.Prop.Break.Wood row open.
  1. To make your own set, choose Add › Miscellaneous › Data Asset, pick the class CFImpact Feedback Set, and add a row to Entries. Set its Event Tag to the tag, and fill in its sounds and effect.
  2. Open Project Settings › Plugins › Crushform Impact Feedback. Set Default Set to your set. A set only needs the rows for the tags you want to hear. A tag without a row uses its closest parent’s, so a row for Crushform.Impact covers every tag that has none of its own.
  3. To give a vehicle its impacts, keep the adapter’s Impact Feedback on, which it is by default. Its CF_ImpactFeedback plays the adapter’s Impact Event Tag. CF_PartImpactFeedback keeps its own tags, and the adapter creates it only with Dirt and Dents on as well. The component table is in Core concepts.

In your own project, a Blueprint plays an impact with the Play Impact node. It takes the tag, the location, the normal (up by default), the intensity from 0 to 1, the surface and an optional source. Impacts from one source share a cooldown. The graph below plays a tree-break impact at the actor’s location when a custom event fires.

The graph plays a tree-break impact at the actor's location when a custom event fires.

Play Impact plays on the machine that calls it only, and on a dedicated server not at all. A game that wants every player to hear it calls it on every machine, for example from a multicast event.

The same in C++ uses the library function, with the tags in CFImpactTags. The block needs the CrushformImpact module in your Build.cs; the module list is in Installation.

#include "CFImpactFeedbackLibrary.h"
#include "CFImpactTags.h"
void PlayTreeBreakHere(const UObject* WorldContext, const FVector& Location)
{
UCFImpactFeedbackLibrary::PlayImpact(WorldContext, CFImpactTags::Impact_Tree_Break, Location);
}

The signature is static void PlayImpact(const UObject* WorldContextObject, FGameplayTag Tag, FVector Location, FVector Normal = FVector::UpVector, float Intensity = 1.f, EPhysicalSurface Surface = SurfaceType_Default, const UObject* Source = nullptr). UCFImpactFeedbackSubsystem::Get(WorldContext)->PlayImpact(FCFImpactEvent) is the same call one level down, for code that builds the event itself.

The project settings are on UCFImpactFeedbackSettings. The row and the components have their own values, which are listed below. The defaults are the plugin’s.

PropertyWhat it doesDefault
UCFImpactFeedbackSettings::DefaultSetThe impact set that plays./Crushform/Impact/DA_CF_ImpactFeedback
UCFImpactFeedbackSettings::MaxAudibleDistanceCmBeyond this distance, in cm, a sound is not played.6000
UCFImpactFeedbackSettings::MaxEffectDistanceCmBeyond this distance, in cm, an effect is not spawned.8000
UCFImpactFeedbackSettings::MinVoiceSecondsThe shortest time a played sound holds a voice slot.0.25
UCFImpactFeedbackSettings::MaxVoiceSecondsThe longest time a played sound holds a voice slot.3
UCFImpactFeedbackSettings::MaxSoundsPerFrameThe most sounds that start in one frame. The rest wait, strongest first, for later frames. 0 turns the cap off.2
UCFImpactFeedbackSettings::SoundQueueSecondsHow long a sound over the frame’s cap may wait; past it, the sound is dropped.0.15
UCFImpactFeedbackSettings::IgnoredHitActorClassesA hit by an actor of one of these classes is no impact.empty
UCFImpactFeedbackSettings::bUseDefaultBreakableHostWhether the plugin maps breakable feedback to impact events.true
FCFImpactFeedbackEntry::VolumeByIntensityThe volume multiplier at intensity 0 and at intensity 1.(0.4, 1.0)
FCFImpactFeedbackEntry::PitchRangeThe random pitch multiplier range.(0.92, 1.08)
FCFImpactFeedbackEntry::MinIntensityAn intensity below this plays nothing. 0 turns the filter off.0
FCFImpactFeedbackEntry::CooldownSecondsThe time between two impacts of one source.0.1
FCFImpactFeedbackEntry::MaxConcurrentVoicesThe most sounds of the row that play at once.4
UCFImpactFeedbackComponent::ImpulsePerKgForFullIntensityThe impulse per kilogram that plays at full strength.600
UCFImpactFeedbackComponent::MinImpulsePerKgThe impulse per kilogram below which a hit is silent.50
UCFImpactFeedbackComponent::ContactGapSecondsThe silence after which the next hit from a component is a new contact.0.1
UCFImpactFeedbackComponent::ContactSpikeRatioWithin a contact, a hit plays only if its impulse is this many times the running impulse.2
UCFNetImpactFeedbackComponent::MinRelayIntervalSecondsThe shortest gap between two impacts this body sends to other players, except for a markedly stronger hit, which is sent sooner.0.5
UCFPartImpactFeedbackComponent::OpenSlamEventTagThe impact event of a slam into the open end of the part’s travel. Empty: no sound there.Crushform.Impact.Part.Slam.Open
UCFPartImpactFeedbackComponent::SlamSpeedForFullIntensityThe speed, in cm/s, of a part’s slam at full strength.500
UCFPartImpactFeedbackComponent::MinSlamSpeedThe speed, in cm/s, below which a slam is silent.40

In any build except Shipping, open the console with the tilde key.

  • crushform.Impact.LogHits 1 turns on the markers. Drive the sedan into a wall, a fence or a tree. Each judged hit leaves a marker for about 5 seconds: green for a contact impact that plays, yellow for a hit within a steady contact, and red for a hit below the minimum. Use crushform.Impact.LogHits 0 to turn them off. It is 0 by default.
  • stat CFImpactFeedback shows the impact cycles.
  • Hit a wall with the car. You hear the sound and see the effect at the contact.

Nothing plays on a dedicated server, or the other players hear nothing

Section titled “Nothing plays on a dedicated server, or the other players hear nothing”

Cause. A dedicated server plays no impact at all. A Play Impact call plays on the machine that makes it only. Impacts from a component reach other players only through a UCFNetImpactFeedbackComponent, which relays them.

Fix. Call Play Impact on every machine that should hear it. For a body’s impacts that other players should hear, use UCFNetImpactFeedbackComponent on it.

Cause. The active set has no row for the tag or for any of its parents, so UCFImpactFeedbackSet::FindEntry finds nothing. A component or adapter whose tag is cleared by hand also plays nothing.

Fix. Add a row for the tag to the set, or a row for its closest parent. Put back the tag on the component or the adapter, or leave it empty to play the plugin’s default.

Cause. There are two cases. A UCFImpactFeedbackComponent observes no primitive until SetObservedPrimitive is called in C++, so a component added in Blueprint alone stays silent. A UCFNetImpactFeedbackComponent observes its owner’s root primitive, and if that root is not a primitive, it logs this line and stays silent:

%s: owner %s has no primitive root; its impacts stay silent

Fix. For the base component, give it the primitive from C++ with SetObservedPrimitive. For a body that should be heard by the other players, use UCFNetImpactFeedbackComponent, and make sure the owner’s root component is a primitive, such as the body’s mesh.

Cause. The hit is below Min Impulse Per Kg (50) or below the row’s Min Intensity, so it is silent. Or the row’s Max Concurrent Voices are all busy, so the impact plays its effect with no sound.

Fix. Lower Min Impulse Per Kg or Min Intensity for the row, or raise Max Concurrent Voices. Turn on crushform.Impact.LogHits 1 to see whether a hit reads red (below the minimum) or was judged at all.

A steady contact plays the impact again and again

Section titled “A steady contact plays the impact again and again”

Cause. The component plays a new impact only when a hit is a spike within its contact: its impulse is at least Contact Spike Ratio (2) times the running impulse. A contact that keeps its impulse does not repeat. A contact that breaks for longer than Contact Gap Seconds (0.1 s) counts as a new one.

Fix. Raise Contact Gap Seconds above a few physics steps if a single impact splits into several. Keep the spike ratio at its default, unless a steady contact still repeats.

For the breaks that these hits come from, see Fences and props and Breakable trees and poles. The vehicle’s own sounds of impact are on its adapter, described in Core concepts.