원클릭으로
audio-system
Use when implementing audio — audio buses, AudioStreamPlayer, spatial audio, music management, SFX pooling, and dynamic mixing
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Use when implementing audio — audio buses, AudioStreamPlayer, spatial audio, music management, SFX pooling, and dynamic mixing
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
Use when working with 2D-specific systems — TileMaps, parallax scrolling, 2D lights and shadows, canvas layers, particles 2D, custom drawing, and 2D meshes in Godot 4.3+
Use when working with 3D-specific systems — materials, lighting, shadows, environment, global illumination, fog, LOD, occlusion culling, and decals in Godot 4.3+
Use when creating Godot editor plugins — EditorPlugin, @tool scripts, custom inspectors, and dock panels
Use when implementing AI movement — NavigationAgent2D/3D, steering behaviors, behavior trees, and patrol patterns
Use when implementing animations — AnimationPlayer, AnimationTree, blend trees, state machines, sprite animation, and code-driven animation
Use when importing and managing assets — image compression, 3D scene import, audio formats, resource formats, and import configuration
| name | audio-system |
| description | Use when implementing audio — audio buses, AudioStreamPlayer, spatial audio, music management, SFX pooling, and dynamic mixing |
All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#.
Related skills: event-bus for decoupled audio triggers, save-load for persisting audio settings, resource-pattern for audio data containers.
| Node | Dimensions | Use For |
|---|---|---|
AudioStreamPlayer | Non-positional | Music, UI sounds, global SFX |
AudioStreamPlayer2D | 2D positional | Footsteps, gunfire, environmental sounds |
AudioStreamPlayer3D | 3D positional | Same as 2D but in 3D space |
Godot routes all audio through buses (like a mixing console).
Master (always exists)
├── Music → volume, effects for background music
├── SFX → volume, effects for sound effects
│ ├── Footsteps → sub-bus for fine-tuning
│ └── Weapons → sub-bus for fine-tuning
└── UI → volume for menu sounds
Setup: Bottom panel → Audio tab → Add buses, set names, route outputs.
Every AudioStreamPlayer has a bus property — set it to the target bus name (e.g., "SFX", "Music").
extends Node2D
@onready var sfx_player: AudioStreamPlayer2D = $AudioStreamPlayer2D
@onready var music_player: AudioStreamPlayer = $MusicPlayer
func _ready() -> void:
# Play background music (looping is set on the AudioStream resource)
music_player.play()
func play_jump_sound() -> void:
sfx_player.stream = preload("res://audio/sfx/jump.wav")
sfx_player.play()
using Godot;
public partial class AudioExample : Node2D
{
private AudioStreamPlayer2D _sfxPlayer;
private AudioStreamPlayer _musicPlayer;
public override void _Ready()
{
_sfxPlayer = GetNode<AudioStreamPlayer2D>("AudioStreamPlayer2D");
_musicPlayer = GetNode<AudioStreamPlayer>("MusicPlayer");
_musicPlayer.Play();
}
public void PlayJumpSound()
{
_sfxPlayer.Stream = GD.Load<AudioStream>("res://audio/sfx/jump.wav");
_sfxPlayer.Play();
}
}
Looping is configured on the AudioStream resource, not the player node:
Always use OGG Vorbis for music (smaller files, good quality). Use WAV for short SFX (no decoding latency). Avoid MP3 for SFX — it adds silence at the start.
Godot uses decibels (dB) for volume. Linear-to-dB conversion is required for sliders.
# Get bus index by name
var bus_index: int = AudioServer.get_bus_index("SFX")
# Set volume in dB directly
AudioServer.set_bus_volume_db(bus_index, -6.0) # -6 dB = ~50% perceived volume
# Convert linear (0.0–1.0) to dB — use for UI sliders
func set_bus_volume_linear(bus_name: String, linear: float) -> void:
var index := AudioServer.get_bus_index(bus_name)
AudioServer.set_bus_volume_db(index, linear_to_db(linear))
# Mute / unmute a bus
AudioServer.set_bus_mute(bus_index, true)
# Read current volume as linear (for displaying on a slider)
func get_bus_volume_linear(bus_name: String) -> float:
var index := AudioServer.get_bus_index(bus_name)
return db_to_linear(AudioServer.get_bus_volume_db(index))
int busIndex = AudioServer.GetBusIndex("SFX");
// Set volume in dB
AudioServer.SetBusVolumeDb(busIndex, -6.0f);
// Linear to dB conversion for UI sliders
public void SetBusVolumeLinear(string busName, float linear)
{
int index = AudioServer.GetBusIndex(busName);
AudioServer.SetBusVolumeDb(index, Mathf.LinearToDb(linear));
}
// Mute / unmute
AudioServer.SetBusMute(busIndex, true);
// Read current volume as linear
public float GetBusVolumeLinear(string busName)
{
int index = AudioServer.GetBusIndex(busName);
return Mathf.DbToLinear(AudioServer.GetBusVolumeDb(index));
}
Add effects to buses in the Audio panel (bottom dock). Common effects:
| Effect | Use For |
|---|---|
Reverb | Cave, cathedral, bathroom ambience |
Delay | Echo effects |
Compressor | Normalize loud/quiet sounds (master bus) |
Limiter | Prevent clipping on master bus |
LowPassFilter | Muffled sounds (underwater, behind walls) |
HighPassFilter | Thin/tinny sound (radio, phone) |
Chorus | Thicken sounds |
Distortion | Gritty/overdrive effects |
EQ | Fine-tune frequency bands |
# Enable/disable an effect on a bus at runtime
var bus_index := AudioServer.get_bus_index("SFX")
var effect_index := 0 # First effect on the bus
AudioServer.set_bus_effect_enabled(bus_index, effect_index, true)
# Apply low-pass filter for "underwater" feel
func set_underwater(enabled: bool) -> void:
var index := AudioServer.get_bus_index("SFX")
# Assumes a LowPassFilter is the first effect on the SFX bus
AudioServer.set_bus_effect_enabled(index, 0, enabled)
Automatically adjusts volume and panning based on distance to the nearest AudioListener2D (or the Camera2D if no listener exists).
Enemy (CharacterBody2D)
├── Sprite2D
└── AudioStreamPlayer2D ← positioned at enemy's location
bus = "SFX"
max_distance = 1000.0
attenuation = 1.0
Key properties:
| Property | Description | Default |
|---|---|---|
max_distance | Beyond this distance, sound is silent | 2000.0 |
attenuation | Volume falloff curve (1.0 = linear, higher = sharper) | 1.0 |
max_polyphony | Max simultaneous instances of this player | 1 |
panning_strength | How much the sound pans left/right | 1.0 |
Same concept but in 3D. Works with AudioListener3D (or the Camera3D).
Key additional properties:
| Property | Description |
|---|---|
unit_size | Distance at which volume is 0 dB |
max_db | Maximum volume cap |
attenuation_model | Inverse, InverseSquare, Logarithmic, Disabled |
doppler_tracking | Enable Doppler effect for moving sources |
# Make a specific camera the audio listener
# 2D: add AudioListener2D as child of Camera2D, call make_current()
# 3D: add AudioListener3D as child of Camera3D, call make_current()
# By default, the current Camera2D/3D acts as the listener.
# Only add an explicit AudioListener if you need a different listening position.
// 2D spatial player
public partial class Footsteps : AudioStreamPlayer2D
{
public override void _Ready()
{
Bus = "SFX";
MaxDistance = 1000.0f; // Pixels at which volume reaches zero
Attenuation = 1.0f; // Linear falloff (higher = sharper)
MaxPolyphony = 4; // Allow overlapping footstep sounds
}
public void PlayStep() => Play();
}
// 3D spatial player
public partial class EngineHum : AudioStreamPlayer3D
{
public override void _Ready()
{
Bus = "SFX";
UnitSize = 4.0f; // Meters at which volume is 0 dB
MaxDistance = 50.0f;
AttenuationModel = AttenuationModelEnum.InverseDistance;
}
}
// Custom listener — overrides the default Camera2D / Camera3D listener.
public partial class FollowCamListener : AudioListener3D
{
public override void _Ready() => MakeCurrent();
}
⚠️ Changed in Godot 4.7: The default
area_maskonAudioStreamPlayer2D/AudioStreamPlayer3Dchanged from1to0(disabled) — theaudio_bus_overridefeature onArea2D/Area3D(e.g. an underwater bus) stops working for players left at the default. Setarea_maskback to layer 1 to restore it; masks explicitly set to anything other than layer 1 keep working. (The migration guide says "AudioStreamPlayer", butarea_maskonly exists on the 2D/3D variants.) See the 4.7 migration guide.
Crossfade between background tracks via a singleton autoload that manages two AudioStreamPlayer nodes and tweens their volume_db. Wire a Music audio bus so the settings menu can adjust music separately.
See references/music-manager.md for the full GDScript and C# autoload (crossfade, push/pop stack, current-track query).
Pre-instantiate a fixed pool of AudioStreamPlayer nodes; play_sfx(stream) finds the next free player and plays. Avoids per-shot instancing churn for high-volume effects (gunshots, footsteps, hits).
See references/sfx-pooling.md for the GDScript + C# pooled player and a 2D positional variant (pool of
AudioStreamPlayer2Dnodes that follow a target).
Wire HSliders in the settings menu to bus volumes via AudioServer.set_bus_volume_db(bus_idx, linear_to_db(value)). Persist with ConfigFile. Use the linear_to_db / db_to_linear helpers — never log-base by hand.
See references/audio-settings.md for the full settings menu wiring with persistence (GDScript + C#).
Three stream types for adaptive music: AudioStreamPlaylist (sequenced or shuffled tracks), AudioStreamSynchronized (multiple stems played in sync — vertical layering for combat intensity), AudioStreamInteractive (clip transitions on triggers — state-driven music). Godot 4.4+ adds AudioStreamWAV.load_from_file() for runtime WAV loading.
Godot 4.7+:
AudioStreamInteractivenow exposesTRANSITION_TO_TIME_PREVIOUS_POSITION(TransitionToTimeenum) to scripts — the destination clip resumes from its last played position if there was a previous transition from that clip, otherwise it plays from its start. Ideal for exploration ↔ combat music that picks up where it left off.
See references/interactive-music.md for the stream-type comparison, GDScript recipes, the 4.7+ resume-position transition, and the 4.4+ runtime-load example.
| Format | Use For | File Size | Decode Latency | Loop Support |
|---|---|---|---|---|
| WAV | Short SFX | Large | None (PCM) | Via import |
| OGG | Music, long SFX | Small | Minimal | Via import |
| MP3 | Music (fallback) | Small | Has padding | Via import |
In the Import dock (select an audio file):
Tip: Keep SFX as 16-bit WAV at 44.1kHz. Godot stores WAV uncompressed in PCK, so they play instantly with zero decode overhead. For music, OGG Vorbis at quality 6–8 is a good balance.
| Symptom | Cause | Fix |
|---|---|---|
| Sound doesn't play | Player not in the scene tree | Ensure the AudioStreamPlayer is add_child()'d before play() |
| Sound plays but no audio heard | Wrong bus name or bus is muted | Check bus property matches a bus name exactly (case-sensitive) |
| Music restarts on scene change | Player is part of the scene, not an autoload | Move music player to an autoload (MusicManager) |
| Positional audio has no panning | No AudioListener or Camera in the scene | Add an AudioListener2D/3D or ensure a Camera is current |
| Sound clicks or pops | Audio file has no fade-in/fade-out | Add a tiny fade (2–5ms) at start/end of WAV in audio editor |
| Too many sounds playing at once | No polyphony limit | Set max_polyphony on players or use an SFX pool |
| Volume slider feels non-linear | Using dB directly instead of linear conversion | Use linear_to_db() / db_to_linear() for slider values |
| 3D audio sounds mono/flat | Stereo source file | Import as mono (Force Mono in Import tab) for 3D spatialization |
| MP3 has silence at start | MP3 format adds encoder padding | Use WAV for timing-critical SFX, OGG for music |
bus property assignedlinear_to_db() / db_to_linear() conversionlinear_to_db(0.0) = -inf)AudioStreamPlaylist, AudioStreamSynchronized, or AudioStreamInteractive (Godot 4.3+) instead of manual track-switching code