Audio is the cheapest way to make a game feel alive and the easiest thing to leave until last. A jump with a sound is twice the jump. A hit that goes "thunk" lands harder than the same hit in silence. Godot's audio system is small once you see the three pieces, so let's wire it up properly.
The player nodes
Godot plays sound through three node types, and picking the right one matters:
AudioStreamPlayerplays a sound at the same volume everywhere. Use it for music and UI clicks.AudioStreamPlayer2Dplays from a position in a 2D world, so it gets quieter with distance and pans left or right. Use it for footsteps, explosions, anything in the world.AudioStreamPlayer3Dis the same idea in 3D.
Drop one in, set its stream to a sound file, and play it:
@onready var jump_sound: AudioStreamPlayer = $JumpSoundfunc jump() -> void: velocity.y = jump_velocity jump_sound.play()Audio buses: mix once, control everywhere
Open the Audio panel at the bottom of the editor. By default there's one bus, Master. Add two more, Music and SFX. Then set each player node's Bus property to the right one.
Now every sound effect flows through SFX and all music through Music, which means you can change the volume of one without touching the other. This is exactly what an options menu needs. Set it up early and a volume slider becomes trivial later.
Volume sliders done right
Here's the part that confuses people. Audio volume in Godot is measured in decibels, which aren't linear. A slider that goes 0 to 1 needs converting, or the bottom half of the slider does almost nothing. Use linear_to_db():
func _on_music_slider_changed(value: float) -> void: # value is 0.0 to 1.0 from the slider var bus := AudioServer.get_bus_index("Music") AudioServer.set_bus_volume_db(bus, linear_to_db(value))linear_to_db() maps a friendly 0-to-1 range onto the decibel scale so the slider feels natural the whole way down. Skip it and your slider will feel broken.
Music that survives scene changes
If you play music with a node in your level, it restarts every time you change scenes. Annoying. The fix is an autoload: a small persistent script that holds your music player and keeps it going across scenes.
# music.gd (autoload named "Music")extends Node@onready var player: AudioStreamPlayer = $AudioStreamPlayerfunc play(track: AudioStream) -> void: if player.stream == track and player.playing: return # already playing this track, don't restart it player.stream = track player.play()Call Music.play(my_track) from anywhere and the music keeps rolling through scene transitions.
A sound effect tip
If the same sound fires rapidly (rapid gunfire, coins), a single player cuts itself off on each new play(). For those, use AudioStreamPlayer with a polyphony setting bumped up, or keep a small pool of players and rotate through them. For most sounds, though, one node per sound is perfectly fine. Don't over-engineer it until you actually hear the problem.
Where to use it
Sound is the layer of polish that makes everything you've built feel finished. Hook it into the systems from your other quests: a pickup sound on inventory items, a hit sound on the health and damage system, a click on every menu button. The free Inventory System quest is a good place to practice, since every item pickup is begging for a satisfying sound.
FAQ
What's the difference between AudioStreamPlayer and AudioStreamPlayer2D?
AudioStreamPlayer plays at a constant volume everywhere, which suits music and UI sounds. AudioStreamPlayer2D plays from a location in the world, so it fades with distance and pans based on position, which suits footsteps, explosions, and other in-world sounds.
How do I make a volume slider in Godot 4?
Route your sounds through an audio bus like Music or SFX, then in the slider's changed handler convert the 0-to-1 value with linear_to_db() and pass it to AudioServer.set_bus_volume_db(). The conversion is what makes the slider feel natural across its whole range.
How do I keep music playing between scenes?
Put your music player in an autoload, a persistent script Godot keeps alive across scene changes. Call its play function from anywhere, and guard against restarting the same track so the music continues smoothly instead of resetting on every scene load.