Your 2D action game has combat, levels, and a HUD. Adding sound effects and music makes hits feel impactful, menus responsive, and the world alive. In this lesson you will wire up Godot 4’s audio system: one-shot SFX, looping music, and simple mixing so levels and UI stay clear.

By the end you will have at least 10 sound effects and background music integrated with basic volume control.


1. How Godot 4 Audio Works

Godot uses AudioStreamPlayer (and AudioStreamPlayer2D for positional sound) to play AudioStream resources. You load .ogg or .wav files as AudioStreamOggVorbis or AudioStreamWAV, assign them to a player node, and call play().

  • AudioStreamPlayer – plays in 2D (no position); good for UI, music, and global SFX.
  • AudioStreamPlayer2D – plays with position and attenuation; good for in-world sounds (footsteps, impacts).

Pro tip: Use Audio Bus layout (Master, Music, SFX, UI) so you can control volume per group and add effects (e.g. reverb on Music) in the project settings.


2. Setting Up Audio Buses

Before adding nodes, define buses so you can mix later.

  1. Open Project > Project Settings > Audio (or the Audio tab in the bottom panel).
  2. In Buses, add buses: Master (default), Music, SFX, UI.
  3. Optionally set default volumes (e.g. Music at -6 dB so it sits under SFX).

You can also add buses at runtime; having them in project settings keeps the mixer consistent.


3. Adding Sound Effects (One-Shots)

For UI and global SFX (button click, pickup, hit), use AudioStreamPlayer nodes.

  1. Add an AudioStreamPlayer node to your scene (e.g. under a GameManager or a dedicated Audio node).
  2. In the Inspector, assign an AudioStream (import your .ogg or .wav).
  3. Set Bus to SFX or UI.
  4. In code, get the node and call play() when the event happens.

Example: play a pickup sound from a script

# In your pickup or game script
@onready var pickup_sound = $AudioStreamPlayer  # or path to your SFX player

func _on_pickup_collected():
    pickup_sound.play()

Use multiple AudioStreamPlayer nodes (or a pool) for overlapping sounds (e.g. several hits at once). For a single “UI beep,” one node is enough.

Common mistake: Calling play() on a node that is still playing. Either use “one shot” players and let them finish, or use multiple players for the same sound so they can overlap.


4. Adding Background Music (Looping)

Music is usually one AudioStreamPlayer on the Music bus, set to loop.

  1. Add an AudioStreamPlayer for music (e.g. under an Autoload or the main game scene).
  2. Assign your music AudioStream (OGG is ideal for music).
  3. Enable Stream > Loop (or use an OGG that loops seamlessly).
  4. Set Bus to Music.
  5. In code, call play() when entering the level (e.g. in _ready() or when the game scene starts).

Example: start music when the level loads

@onready var music_player = $MusicPlayer

func _ready():
    music_player.play()

To cross-fade or switch tracks later, use a short tween on volume_db or swap the stream and call play() again.


5. Connecting Sounds to Game Events

Wire SFX to the events you already have:

  • Player hit – play a hit or hurt sound when damage is applied.
  • Enemy hit / death – play impact or explosion.
  • Pickup / collectible – play a short “collect” sound.
  • Button / UI – play a click or confirm on button press.
  • Weapon fire – play a shoot sound (and optionally a reload).

Use signals or direct method calls from your existing code (e.g. when take_damage() runs, call sfx_hit.play()). Keep audio logic in one place (e.g. an AudioManager autoload) if the project grows.


6. Volume and Mixing

  • Per-bus volume: Use AudioServer.set_bus_volume_db(bus_index, db) to lower Music during cutscenes or raise SFX.
  • Per-player volume: Adjust Volume Db on the AudioStreamPlayer in the Inspector or in code.
  • Duck music when paused: In your pause menu, lower the Music bus and restore it on unpause.

Pro tip: Aim for about 10 distinct SFX (hit, death, pickup, shoot, UI click, etc.) and one looping music track. You can add more in a later pass; consistency matters more than quantity.


7. File Format and Import

  • SFX: WAV or OGG; short files (under a few seconds). Godot imports them as AudioStreamWAV or AudioStreamOggVorbis.
  • Music: OGG with loop points or a seamless loop. Place files in res://assets/audio/ (or your chosen folder) and drag into the Inspector.

If a sound is too loud or quiet, adjust Volume Db on the stream or the bus.


Troubleshooting

  • No sound: Check the bus is not muted and the device volume is up. Ensure play() is called (e.g. no early return or wrong node path).
  • Sound plays once then never again: If you reuse the same node and call play() while it is still playing, it may restart. For one-shots that can overlap, use several AudioStreamPlayer nodes or a small pool.
  • Music does not loop: Enable Loop on the stream, or export the OGG with a seamless loop so the end blends into the start.

Mini-Challenge

Add at least 10 sound effects and one music track: one SFX each for player hit, enemy hit, enemy death, pickup, shoot, UI click, and a few extras (e.g. footstep, door, power-up). Play background music when the level starts. Set buses to Music and SFX and tweak volumes so SFX are clear and music does not overpower.


Recap and Next Step

You set up audio buses, added AudioStreamPlayer nodes for SFX and music, wired them to game events, and used the Music and SFX buses for mixing. Your game now has clear feedback for combat, UI, and atmosphere.

In Lesson 10 you will add sprite animations and visual effects: AnimatedSprite2D, particle systems, and screen shake so the game feels even more responsive and polished.

For more on game audio, see our Audacity for Game Audio guide and the Game Audio section. Found this useful? Bookmark the course and share your build with the community.