Bite-Sized Godot: Audio volume sliders
Volume sliders are an essential component of any decent options menu. To get started with making them, if you haven’t already, go to the Audio tab on the bottom panel of the Godot editor and add a bus for each category of audio you want to adjust. By default, there’s a Master bus that all audio pipes through, but you’ll probably want to also add at least Music and Sound Effects buses so the user can tweak them separately. If you also have voice acting, you’ll probably want add a Dialogue bus as well.
After you’ve added your buses, you’ll want to go through your project and make sure all audio is piped to the correct bus. This can be done by selecting the relevant audio player node and changing the Bus property in the Inspector.
Once that’s done, it’s time to create our volume control. Make a new scene with an HSlider as the root node with a range of 0 to 1, a step of 0.001, and attach a script to it. We use 0 to 1 because we’ll eventually need to translate this value to a more audio-friendly one, but more on that in a bit. In the script you created, add an exported string parameter named bus_name
, which will, shockingly, be the name of the bus the slider should control.
# volume_slider.gd
extends HSlider
@export
var bus_name: String
Now we just need to wire everything up. In Godot, you don’t access audio buses by name, but rather by index, which can be looked up by name. So add a bus_index
variable to your script so you only have to do the lookup once, and in your _ready()
function, save the output of AudioServer.get_bus_index(bus_name)
, which looks up the bus index by name, to this variable.
# volume_slider.gd
extends HSlider
@export
var bus_name: String
var bus_index: int
func _ready() -> void:
bus_index = AudioServer.get_bus_index(bus_name)
For setting the volume on the bus, connect the value_changed
signal of the slider, which fires every time the slider value changes, to a function and call AudioServer.set_bus_volume_db(bus_index, linear_to_db(value))
(in Godot 3, replace linear_to_db
with linear2db
) to set the volume of your bus. We call linear_to_db
on the slider value to convert it to a more audio-friendly value, as the slider is linear but people don’t perceive volume in a linear fashion. By calling linear_to_db
on the slider value, you can make the adjustments on the slider sound more like they look.
Here’s a side-by-side example. First, with this conversion:
And then without:
# volume_slider.gd
extends HSlider
@export
var bus_name: String
var bus_index: int
func _ready() -> void:
bus_index = AudioServer.get_bus_index(bus_name)
value_changed.connect(_on_value_changed)
func _on_value_changed(value: float) -> void:
AudioServer.set_bus_volume_db(bus_index, linear_to_db(value))
You can also do the inverse and convert a decibel value to a linear one, which can be handy for initializing the slider to the current bus volume so that your options menu can be shared on different screens and still reflect the current volume. To do so, add value = db_to_linear(AudioServer.get_bus_volume_db(bus_index))
to your _ready
function after you look up the index:
# volume_slider.gd
extends HSlider
@export
var bus_name: String
var bus_index: int
func _ready() -> void:
bus_index = AudioServer.get_bus_index(bus_name)
value_changed.connect(_on_value_changed)
# If you're using Godot 3, replace db_to_linear() with `db2linear()
value = db_to_linear(AudioServer.get_bus_volume_db(bus_index))
func _on_value_changed(value: float) -> void:
# If you're using Godot 3, replace linear_to_db() with linear2db()
AudioServer.set_bus_volume_db(bus_index, linear_to_db(value))
And with that, your slider is ready to go!
In your options menu, or wherever you want to add a volume slider, add an instance of your volume control scene for each audio bus you have, including Master so the player can adjust the audio for the entire game easily, and set the bus_name
property on each as appropriate (note that this IS case-sensitive). Now, when you run your game, you should be able to adjust each slider and have those changes reflected in your game’s audio.