Audio Implementation of a system driven by physics collisions in UE4 using blue prints.
What we want to do here is to replicate the interactions of different materials that produce a sound whenever they are thrown or dragged onto each other. These systems can be extremely complex since we are going into physics simulation territory and there are a lot of possible scenarios we have to cater for in the game. It is therefore important to scale the variables from physical events to numbers we can use to drive our audio systems. But most of the time, the typical use cases in a game will be objects that will be thrown on other objects or surface. For this reason, we should start with a simple but effective system that can handle some core functions like:
- Blend impact sounds depending on the force of the impact.
- Blend item sounds with the surface sounds they are interacting with.
- Prevent low value sounds from triggering
- Prevent weird physics behavior when the player steps on items.
- First step is to define some surface types, create physical materials and assign them to the respective surface types.
2. Create an actor blue print (BP) for the object/prop you want to include in the physics collision system. I’m not going to go explain how to a mesh to build a prefab and focus on the audio logic in the event graph, assuming you already know about this. Wile you are in the Viewport, just make sure that you have
ticked “Simulate Physics” and “Simulation Generates Hit Events” in the details panel. Check that “Collision Presets” is set to “Physics Actor” and populate the physics material for the object in the “Physics Material Override” box.
In the Event Graph, we will start with an event hit node. We will use the “Normal Impulse”, which will return the velocity of the hit event. This goes into a vector length node, which gives us the strength of the impulse as a single float. From there, we exclude impulses with a force smaller than 100 and route to a “Do Once” node to prevent uncontrolled re-triggering.
Now we break the hit result to get access to the physics material. Therefore, we must create a map variable with physical material as the key and sound cue as the value. There we need to map the corresponding physical materials and sound cues respectively. To be able to find the physical material on this map, we need to connect it to a “Find” node and hook it up to the Phys Mat return of the Break Hit Result node. The result is routed to set a new sound cue object variable as the physical material sound.
We then get the Phys Mat return from the “Break Hit Result” node and set it its value to a variable “PhysMatSound”. Also, from the “Vector Length” node we make a second connection into a “Normalize To Range” node to be able to properly scale the values of the impact force (into a range between 0-1) and set it to a “Force” variable. This can be used to modulate the volume for each sound that will be generated.
Finally, we use the Hit Location vector return from the “Event Hit” node and store it as a vector variable “HitLocation” to define the event location.
To prevent weird playback behavior when the player walks over the collision objects, we can break away with a sequence node after the Do Once node and connect the Blocking Hit return from the “Break Hit” return from the “Event Hit” event and set it as true condition of a “Branch” node. On true, we’ll execute a “Set Collision Response to Channel” with the target referencing the static mesh of the object. Set the Channel to “Pawn” and the New Response to “Ignore”. This prevents physics interaction on the player pawn after the item has registered at least one hit.
Now we want to play a different sound depending on the impact strength. We want a simple but effective system, so it makes a lot of sense to differentiate between light, medium and heavy object impact sounds. At the center of this system is the “Play Sound at Location” node, where we can hook up a sound cue. Hooking up the “Location” vector variable into the location input makes sure that the sound will play at the relative location of the impact. We can hook up different attenuation curves for the light, medium and heavy impact sounds, to make sure that the heavy impact sounds, which are typically much louder than the light impact sounds, will be heard at a further distance.
We need to find a way to seemingly blend the sounds together. This can be achieved by riding the Force values through a curve like shown in the image below. Since our system makes use of three different sounds, we can use a vector-curve with three channels for that reason and hook it up as target of a “Get Vector Value” node. Then we can connect the Force value to the In Time Input, break the vector3 variable and use the x-value to drive the volume of the light impact sounds.
If we want to adjust the volume of the impact sound in relation to the material sound of the surface, we can add reference to a float variable called “ItemVolumeMult” and multiply its value with the x-value from the vector.
Finally, we can copy the hole system two times and use the return y-value to ride the volume of the medium impact sound and the z-value for the heavy impact sound.
We again start with the “Play Sound at Location” node. We then reference the “PhysMatSound” and “Location” variables and attach an attenuation curve “Attenuation Settings”. Furthermore, we then create another map variable for the physics surface materials “SurfaceVolMap” where we can hook up the physical material and set the volume accordingly. This volume value is then modified by multiplying it with the “Force” value and if we need further adjustment we can then multiply this result with a value stored in a variable named “SurfaceVolMulti”.