This article will cover using the Godot FMOD plugin to play sound assets that are generated from an FMOD project. If you have not already integrated FMOD with Godot, then check out my tutorial here to get started.

We will be creating a character that walks around with audible footsteps. The sound of the footsteps will vary with each footstep and can be set to different surfaces.

Creating FMOD Banks

We will be using sound banks from the FMOD examples project that is installed with FMOD Studio.

Step 1: If you do not have FMOD Studio installed, then download and install it from the FMOD Downloads page. Ensure that it matches the same version of the FMOD Engine that you have installed to work with the fmod-gdnative plugin.

Step 2: Run the FMOD Studio application.

Step 3: Open the FMOD Examples project. This project comes with FMOD Studio and is located in its installation folder. On Mac OS X the project is located at /Users/<username>/Library/Application Support/FMOD Studio/2.00.15/Examples/Examples.fspro.

<FMOD Studio installation directory>
└── Examples
    └── Examples.fspro

Step 4: Select File and then Build from the menu. This will build all of the sound banks in the examples project and export them in a Build folder alongside the examples project. You should now have the following files in your directory structure.

<FMOD Studio installation directory>
└── Examples    
    ├── Build    
    |   └── Desktop    
    |       ├── Dialogue_CN.bank    
    |       ├── Dialogue_EN.bank    
    |       ├── Dialogue_JP.bank    
    |       ├── Master.bank    
    |       ├── Master.strings.bank    
    |       ├── Music.bank    
    |       ├── SFX.bank    
    |       ├── Vehicles.bank    
    |       └── VO.bank    
    └── Examples.fspro

We will be using the Master.bank, Master.strings.bank, and SFX.bank files.

Creating the Main Character

Step 1: Create a new Godot project that uses the fmod-gdnative plugin. See my tutorial here if you need help getting started.

Step 2: Create a new Node2D scene by selecting Scene and then New Scene from the menu. Choose the 2D Scene as the root node.

Step 3: Rename the root node to Player by double clicking on it.

Step 4: Save the scene as Player.tscn by selecting Scene and then Save Scene.

Step 5: Create a child Sprite node by pressing the plus button under the Scene tab. Search for Sprite and click Create.

Player node tree

Step 6: Create a new texture for the sprite node by clicking on the [empty] field to the right of the Texture property in the Inspector. Click Load and then select the Godot icon.png and click Open.

Step 7: Click the play triangle in the top right hand corner of the editor to run the game. If you are prompted to set a main scene, then accept your player scene as the main scene for now. You should see the Godot icon in the top left of the window.

Adding Movement

Next we will add movement to the main character.

Step 1: Add a new script to the Player node by first clicking the root Player node and then clicking the script icon to the right of the Filter nodes search bar. Leave the defaults and click Create.

Step 2: The script editor should automatically open. If it does not then switch to it by clicking the Script tab at the top of the editor and select the Player.gd file.

Step 3: Paste the following code into the Player.gd file. This will allow the player to move around the screen based off of the project’s default input actions. If you defined different input actions, then ensure you use them in the is_action_pressed() functions instead of the project defaults.

const SPEED: int = 200
var _velocity = Vector2.ZERO

func _physics_process(delta):
	_get_input()
	position = position + _velocity * delta

func _get_input():
	_velocity = Vector2.ZERO
	if Input.is_action_pressed("ui_right"):
		_velocity.x = 1
		_velocity.y = 0
	if Input.is_action_pressed("ui_left"):
		_velocity.x = -1
		_velocity.y = 0
	if Input.is_action_pressed("ui_down"):
		_velocity.x = 0
		_velocity.y = 1
	if Input.is_action_pressed("ui_up"):
		_velocity.x = 0
		_velocity.y = -1
	_velocity = _velocity.normalized() * SPEED

If you run the game you should now be able to move the Godot icon around the window.

Initializing FMOD

Next we need to initialize FMOD and load the sound banks we are going to use.

Step 1: Create a new folder in your project by right clicking in the FileSystem panel and selecting New Folder. Name it banks.

Step 2: Copy the Master.bank, Master.strings.bank, and SFX.bank files into the newly created banks folder. You should now have the following directory structure in your Godot project.

<Project root, i.e. res://>
├── addons
|   └── <fmod-gdnative plugin>
├── banks
|   ├── Master.bank
|   ├── Master.strings.bank
|   └── SFX.bank
├── icon.png
├── Player.gd
├── Player.tscn
└── <other project files>

Step 3: We first need to initialize the FMOD engine before using it. Add the following line into the player’s _ready() function.

Fmod.init(1024, Fmod.FMOD_STUDIO_INIT_NORMAL, Fmod.FMOD_INIT_NORMAL)

This line initializes the FMOD engine with a max of 1024 channels and passes the default initialization flags to both the FMOD Studio and FMOD Core systems.

Step 4: Load the sound banks that we built with FMOD Studio (still inside of the _ready() function).

Fmod.load_bank("res://banks/Master.strings.bank", Fmod.FMOD_STUDIO_LOAD_BANK_NORMAL)
Fmod.load_bank("res://banks/Master.bank", Fmod.FMOD_STUDIO_LOAD_BANK_NORMAL)
Fmod.load_bank("res://banks/SFX.bank", Fmod.FMOD_STUDIO_LOAD_BANK_NORMAL)

At this point you can run your game and you should see output that indicates FMOD was successfully initialized and that the sound banks were loaded. If you did not see the expected output, then double check your initialization above and ensure you are loading the Master.strings.bank file before any other bank file.

Fmod Gdnative interface managed by a GDScript wrapper
FMOD Sound System: Successfully initialized
FMOD Sound System: LOADING BANK ./banks/Master.strings.bank
FMOD Sound System: BANK bank:/Master.strings LOADED
FMOD Sound System: LOADING BANK ./banks/Master.bank
FMOD Sound System: BANK bank:/Master LOADED
FMOD Sound System: bus:/SFX/Character added to buses
FMOD Sound System: bus:/SFX/Ambience added to buses
FMOD Sound System: bus:/SFX/Explosions added to buses
...

Playing a Sound

Now it’s time to make some noise! We can add footsteps for our character by triggering an FMOD event and letting the FMOD engine play the sound for us.

Step 1: We need to create a Timer node that will continuously trigger sound events while moving. Click the Player node and then the plus sign in the Scene panel. Search for timer, select the Timer node, and click Create.

Adding a timer node

Step 2: Leave the default properties for the Timer. i.e. Process Mode of Idle, Wait Time of 1, One Shot as Off, and Autostart as Off.

Step 3: Select the Timer node on the Scene panel and then select the Node panel. Select the Signals tab if it is not already selected.

Step 4: Connect the timeout() signal of the Timer node to the Player node by selecting timeout() and clicking Connect. Ensure you are connecting to the Player node and leave the defaults for the connection. Then click Connect. This will create a new method in the Player node’s script called _on_Timer_timeout().

Timer signal connection

Step 5: Switch back to the script editor and add the following code inside of the new _on_Timer_timeout() method.

Fmod.play_one_shot("event:/Character/Player Footsteps", null)

This will tell the FMOD engine to play the Player Footsteps event from the SFX bank we built earlier.

Step 6: Now we just need to start and stop our Timer at the appropriate time. Add the following lines inside of the _physics_process() function. This will simply start our timer if the Player’s velocity is not zero, meaning the player is moving, and stop it otherwise. We also fire off one footstep immediately when starting the timer so we are able to hear the initial footstep.

if _velocity != Vector2.ZERO:
	if $Timer.is_stopped():
		Fmod.play_one_shot("event:/Character/Player Footsteps", null)
		$Timer.start()
	else:
		$Timer.stop()

Running the game should now allow you to hear footsteps at a one second interval while moving. You can of course play with the Timer Wait Time parameter to change the frequency of the steps.

Also notice that the footsteps vary with each step even though we call a single FMOD event. This is just one of the many powerful features of FMOD. In this scenario, the event was set up with multiple footstep sounds and FMOD randomly chooses one on each event call.

Adding Different Surfaces

It’s also possible to pass parameters to FMOD events, which can then be used to change the outcome of what the sound will be. We can use this method to adjust the sound of our player’s footsteps all while using the same event!

The Player Footsteps event can take a surface parameter that defines what surface is being walked on, either carpet, grass, or a wood floor. The surface parameter is defined in FMOD Studio and can be viewed by selecting the Banks tab and then the Character/Player Footsteps event under the SFX bank. We simply need to provide this surface parameter to the FMOD event with the desired value to change the sound of the footsteps.

FMOD Studio player footsteps event

Step 1: First let’s define the available surfaces with the other variables at the top of the Player.gd file.

enum Surfaces {
	CARPET,
	GRASS,
	WOOD,
}

Step 2: Change the two play_one_shot() calls to the following. This will fire the same player footsteps event, but will specify that it is on a grass surface, which has a value of 1.

Fmod.play_one_shot_with_params("event:/Character/Player Footsteps", null, {"surface": Surfaces.GRASS})

You should now be able to move the player around and hear a different sound for the footstep, this time as if the player were walking on grass! You can change the surface again to Surfaces.WOOD to hear the player walking on a wooden floor.