Footsteps Audio System in Unreal Engine and Wwise (Blueprints and C++)

Si prefieres leer una versión en Español, da click en este botón =>

Unreal Engine Version: 5.0.3

Wwise Version: 2021.1.10.7883

This blog post shows you how to create a footsteps audio system in Unreal Engine 5 and Wwise. This system uses a line trace spawned from the Player Character's location down to the floor. This line trace will gather information about the Physical Material of the surfaces and set Ak Switch values to change the type of footstep sounds.

I implemented the same system twice for this test project, one using Blueprints visual scripting and another using native C++. Here is the list of essential tools and keywords used for this project:

I programmed all the functionality inside the MyUE5ProjectCharacter C++ parent class, the BP_ThirdPersonCharacter child blueprint class, and the animation blueprint ABP_Manny.

Important:

Please consider that this guide does not intend to teach creative sound design. Instead, it exclusively focuses on game audio's implementation and programming aspects.


Download the project here:

IMPORTANT!

〰️

IMPORTANT! 〰️

Prerequisites:

  1. Create an empty C++ third-person project called “MyUE5Project”.

  2. Download and integrate the Wwise plugin into your project through the Wwise Launcher.

  3. Activate Event-Based Packaging

For this tutorial to make sense, you need to know how to integrate the Wwise plugin into Unreal Engine. Additionally, consider reading and referencing my previous post about UPROPERTY & UFUNCTION:

IMPORTANT!

〰️

IMPORTANT! 〰️

 

Wwise Setup:

Inside the Wwise project, create a switch group on the Game Syncs tab called Footsteps. Add four switches, one per footstep type.

 

Go to the Audio tab and create a Switch Container called “Footsteps” with four Random Containers inside; one per footstep type. Drag and drop the appropriate audio files inside these containers. Set the switch group and the default switch on the switch container. Drag and assign the random containers to their correct switches.

Right-click on the “Footsteps” switch container and create a new event called “Play_Footsteps”.

 

As an additional step, go to the voice section in the random container and set a random pitch modulation by right-clicking on Pitch > Enable Randomizer. This setting adds further variation to the footstep sounds. Repeat this process for every Random Container on the event.

Save the project.

 

Materials and Physical Materials:

Environmental Artists use Material and Physical Material assets to define the look and physics simulation of meshes in the game. As game audio artists and programmers, we can use these materials attached to surfaces and a Line trace to set FMOD parameters dynamically.

Create a Materials folder and add a Material and a Physical Material per each required surface. For this project, I created four different materials.

 

Double click on each material and set its color and Physical Material on the editor.

Go to Window > Place Actors > Plane, drag and position these new surfaces in the viewport, and then their Material. Additionally, you can add a name to them with a Text Render Component.

 

C++ Setup:

I implemented this project's properties and a Ak Audio Component in C++. 

The blueprint class will inherit all these properties from the parent and expose them in the Blueprint graph. Finally, I created two functions in C++ and two functions in Blueprints that do the same to show you how both systems mirror each other.

Important:

I use Doxygen style comments to explain the code. These comments won’t compromise the code's functionality or compilation. Feel free to copy the code as it’s written here.

Build.cs:

Open the solution in your IDE and locate MyUE5Project.Build.cs in MyUE5Project > Source, and add "AkAudio" and "PhysicsCore" as dependencies to the build.

/** Add "AkAudio" and "PhysicsCore" to be able to use and compile Wwise's API and UPhysicalMaterial in C++ */
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "AkAudio", "PhysicsCore"});

Property and Function Declarations:

Go to MyUE5Project > Source, and open MyUE5ProjectCharacter.h. Include these directives:

.h file:

#include "AkComponent.h" // Include this directive to access Ak Component.
#include "AkSwitchValue.h" // Include this directive to access Ak Switch Value.
#include "PhysicalMaterials/PhysicalMaterial.h" // Include this directive to work with Physical Materials.

Declare an Ak Audio Component, a TMap, a boolean, and a float.

.h file:

/** Ak Audio Component. Created in the class constructor. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Audio")
UAkComponent* AkAudioComponent;

/** A map data structure. Holds Physical Materials as keys and Ak Switch Values as values.
 *  These values will set the correct switch in Wwise */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Audio")
TMap<UPhysicalMaterial*, UAkSwitchValue*> PhysicalMaterialMap;

/** Boolean property that sets AddOnScreenDebugMessage function on and makes the line trace visible in game. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Audio")
bool bPrintDebug;

/** Defines how long the line trace extends from our Character's location on the Z vector.
 *  Positive numbers up vector, negative numbers down vector. -150cm set as default */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Audio")
float Offset = -150;

Declare two functions, GetPhysicalMaterialByLineTrace() and SetFootstepsParameter().

.h file:

/**
 * @brief Gets a reference of the floor's Physical Material with a Line trace.
 * @param OffsetZ How far the line trace extends from our Character's center.
 * @param bDebug Sets visibility for the Line trace. true: Visible, false: Not Visible
 * @return A Physical Material reference
 */
UFUNCTION(BlueprintCallable, Category="Audio")
UPhysicalMaterial* GetPhysicalMaterialByLineTrace(const float &OffsetZ, const bool &bDebug);

/**
 * @brief Gets a Physical Material reference and sets the appropriate Ak Switch value in Wwise. 
 * @param HitPhysicalMaterial A Physical Material Reference
 * @param bDebug Sets visibility for printing the current Physical Material to the screen. true: Visible, false: Not Visible
 * @param DefaultAkSwitchValue Default Ak Switch value.
 */
UFUNCTION(BlueprintCallable, Category="Audio")
void SetFootstepsSwitch(const UPhysicalMaterial* HitPhysicalMaterial, const bool &bDebug, const UAkSwitchValue* DefaultAkSwitchValue);

C++ and Blueprint Implementation:

In this section, I show you how to access the Line trace in the Kismet System Library and how to create an Ak Audio Component. Finally, I show you the BP_ThirdPersonCharacter implementation in the blueprint graph and then the C++ implementation in the MyUE5ProjectCharacter.cpp file.

.cpp file:

#include "Kismet/KismetSystemLibrary.h" // Include this directive to access the Line Trace functions.

Ak Audio Component in the Class Constructor:

Create an Ak Audio Component in the class constructor. The constructor has the same name as the class: MyUE5ProjectCharacter::MyUE5ProjectCharacter(). This Ak Audio Component will hold the footsteps Ak audio event and follow our Character's location in the world. Additionally, this component lets us define switch values before creating an instance of its event.

.cpp file:

// Create an Ak Audio Component. 
AkAudioComponent = CreateDefaultSubobject<UAkComponent>(TEXT("Footsteps Audio Component")); //Creates the Ak Audio Component.
AkAudioComponent->SetupAttachment(GetMesh()); // Attaches the component to the Skeletal Mesh so the sound travels with our Character.

Get Physical Material By LineTrace

This function creates a line trace and returns the Physical Material it hits.

Blueprint:

.cpp file:

UPhysicalMaterial* AMyUE5ProjectCharacter::GetPhysicalMaterialByLineTrace(const float &OffsetZ, const bool &bDebug)
{
   const FVector LineStart = GetActorLocation(); //Sets the Line Start at our Character's location.
   const FVector LineEnd = FVector(LineStart.X, LineStart.Y, LineStart.Z + OffsetZ); //Sets the Line End at our Character's location plus the offset.
   EDrawDebugTrace::Type DebugType; // This enumeration is used to set the visibility of the line trace.
   FHitResult HitResult; // This struct will hold the line trace hit results.   
	
   if (bDebug) // Activate line trace visibility?                          
	DebugType = EDrawDebugTrace::ForDuration;
   else                                          
	DebugType = EDrawDebugTrace::None;       

   // Line trace function.
   UKismetSystemLibrary::LineTraceSingle(this, LineStart, LineEnd,UEngineTypes::ConvertToTraceType(ECC_Visibility), false,TArray<AActor*>(), DebugType, HitResult, true, FLinearColor::Red, FLinearColor::Red, 2.0f);
	
   return Cast<UPhysicalMaterial>(HitResult.PhysMaterial); // Cast and return the Physical Material from HitResult.
}

Set Footsteps Parameter

This function gets a Physical Material reference and tries to find it as a key in our TMap. If it succeeds, it will set the value related to that key as the current Ak Switch. Additionally, it will print the current Physical Material name to the screen.

Blueprint:

.cpp file:

void AMyUE5ProjectCharacter::SetFootstepsSwitch(const UPhysicalMaterial* HitPhysicalMaterial, const bool &bDebug, const UAkSwitchValue* DefaultAkSwitchValue)
{
/* Checks if the map contains the Physical Material as a key before setting the Ak Switch value.
*  The game will crash if you attempt to find a null reference or a Key that doesn't exist in the map.*/
if (PhysicalMaterialMap.Contains(HitPhysicalMaterial)) 
{
	AkAudioComponent->SetSwitch(PhysicalMaterialMap[HitPhysicalMaterial], "", ""); // Sets the Ak Switch value of the map's key.

	if (bDebug) // If true, prints the name of the Physical Material to the screen and "C++ Implementation".
	   {
	   GEngine->AddOnScreenDebugMessage(0, 1, FColor::Orange,
	   "Physical Material: " + HitPhysicalMaterial->GetName());
           GEngine->AddOnScreenDebugMessage(1, 1, FColor::Red, "C++ Implementation");
	   }
}
else // If a valid key wasn't found, sets the default AK Switch value; otherwise, the last switch will remain.
   {
   AkAudioComponent->SetSwitch(DefaultAkSwitchValue, "", ""); 
   }
}

Full Blueprint Graph:

.cpp file:


Save your code and compile it in the editor.

 
 

You should be able to see the Ak Audio Component and all the properties in the components and variables tabs in the BP_ThirdPersonCharacter class. Assign your footsteps event to this component.


The Animation Blueprint:

In the BP_ThirdPersonCharacter, go to the Physical Material Map previously defined in C++ and assign the Physical Materials as keys. Fill in the map's values with the Ak Switch values defined in Wwise.

Right-click on the graph and create a custom event function. I named this function BPF_PlayFootsteps. Finally, drag the Ak Audio Component to the graph and call its Post Associated Ak Event function.

All the functionality for dynamically changing Ak Switch values is ready. Now, we need to trigger the footsteps event. To achieve this, implement this functionality in the Character's animation blueprint. Open the Content Drawer, go to Content > Characters > Mannequins > Animations, and open ABP_Manny. Go to the upper right corner of the editor and click on the Animation Sequence button.

In the Asset Browser, open the "MF_Run_Fwd" sequence and add a notify track. Then right-click on it and select Add Notify > New Notify. Call your notify "Footstep." Duplicate your notify on every frame where the skeletal mesh feet hits the floor. Repeat the same process for "MF_Walk_Fwd" and "MM_Walk_InPlace."

Go back to the Animation Blueprint and call the Event Blueprint Begin Play function to cast and save a reference to the BP_ThirdPersonCharacter to a variable once the game begins. Call the notify by searching for the AnimNotify_Footstep function. Finally, call the BPF_PlayFootsteps custom function.

Complete Blueprint Implementation:

I created a branch for this project to select between the blueprint implementation and the native C++ one.


THE END

〰️〰️〰️

THE END 〰️〰️〰️

Previous
Previous

Spatialization #1 in Unreal Engine and Wwise (Blueprints and C++)

Next
Next

Footsteps Audio System in Unreal Engine and FMOD (Blueprints and C++)