Voltar para o Blog
Quest Log

Audio Buses no Godot: Como Mixar Música e Efeitos Sonoros

Mesa de mixagem estilizada representando os audio buses do Godot com canais de música e efeitos

Aprenda audio bus no Godot 4: crie buses de música e SFX, controle volume por código com sliders, aplique reverb e low pass, e salve a config do jogador.

Audio Buses no Godot: Como Mixar Música e Efeitos Sonoros

Todo jogo precisa de um slider de "volume da música" e outro de "volume dos efeitos". Parece detalhe, mas é o tipo de coisa que o jogador espera encontrar no menu de opções, e que vira gambiarra rápido se você não estruturar direito. A resposta certa pra isso no Godot é o sistema de audio bus, e a boa notícia é que ele já vem pronto na engine: você só precisa entender como rotear o som.

Um audio bus no Godot funciona como um canal de uma mesa de mixagem. Todo som do jogo passa por um bus antes de chegar nos alto-falantes, e em cada bus você controla volume, mute, solo e uma cadeia de efeitos. Em vez de ajustar o volume de cada AudioStreamPlayer um por um (já vi projeto com 40 players e um script percorrendo todos pra abaixar a música, não faça isso), você ajusta o bus uma vez e tudo que passa por ele obedece.

Nesse tutorial eu monto o layout clássico Master/Music/SFX, ligo os players nos buses certos, escrevo o código dos sliders de volume, aplico efeitos úteis (o abafado de menu de pause é o meu favorito) e salvo a configuração do jogador em disco. Tudo em GDScript do Godot 4.x, testável como está.

O que é um audio bus e por que o Master não basta

Abra qualquer projeto Godot e olhe o painel Audio na parte de baixo do editor (na mesma fileira de Output e Debugger). Você vai ver um único canal chamado Master. Ele sempre existe, não pode ser removido, e é por onde todo som sai por padrão.

Dá pra fazer um jogo inteiro só com o Master? Dá. Mas aí você não consegue:

  • Abaixar a música sem abaixar os efeitos (o pedido número um de qualquer menu de opções)
  • Aplicar reverb só nos sons do cenário sem afetar a interface
  • Abafar todo o jogo quando o pause abre, mantendo a música do menu limpa
  • Fazer fade out da trilha numa transição de cena sem mexer em cada player

Cada um desses problemas se resolve com um bus dedicado. A regra prática que eu uso: um bus pra cada grupo de som que precisa de controle independente. Pra maioria dos jogos, três ou quatro buses resolvem.

Criando os audio buses no Godot: Master, Music e SFX

No painel Audio, clique em Add Bus duas vezes. Renomeie os novos canais pra Music e SFX (clique duplo no nome). Pronto, o layout existe. Ele fica salvo em res://default_bus_layout.tres e carrega junto com o projeto.

Repare no dropdown na parte de baixo de cada canal: é o send, pra onde aquele bus despeja o som depois de processar. Music e SFX vêm apontando pra Master, e é isso que você quer. O fluxo fica assim:

AudioStreamPlayer (música)  →  Music  →  Master  →  saída
AudioStreamPlayer (tiro)    →  SFX    →  Master  →  saída

Essa hierarquia é o pulo do gato: o Master vira o volume geral. Abaixou o Master, abaixou tudo. Abaixou só o Music, a música cai e os efeitos continuam. É exatamente o comportamento dos três sliders de opções (Geral, Música, Efeitos) que todo jogo tem.

Se o seu jogo cresce, dá pra ir além: um bus UI pra sons de interface (que não devem receber reverb de caverna), um bus Ambience pra som de ambiente, um bus Voice pra diálogo. Buses podem mandar som pra outros buses que não o Master, então dá pra ter um bus "World" agrupando SFX e Ambience. Comece simples e adicione quando sentir falta.

Roteando os players pros buses

Criar o bus não muda nada sozinho: os players continuam tocando no Master. Em todo AudioStreamPlayer (e nas variantes 2D e 3D), existe a propriedade Bus no Inspector. Selecione o player da música e troque pra Music; nos players de efeito, troque pra SFX.

Por código é uma linha:

$MusicPlayer.bus = "Music"
$ShootSound.bus = "SFX"

Detalhe que pega muita gente: a propriedade é o nome do bus, como string. Se você digitar "music" minúsculo ou renomear o bus depois, o player volta silenciosamente pro Master. Quando um som "ignora" o slider de volume, esse é o primeiro lugar pra olhar.

Controlando volume por código: dB e linear

Aqui mora a parte que mais confunde. O Godot mede volume de bus em decibéis, e decibel é escala logarítmica: 0 dB é o volume original, -6 dB é mais ou menos metade da intensidade percebida, -80 dB é silêncio na prática. Um slider de 0 a 1 ligado direto em dB fica horrível: quase todo o curso do slider não faz diferença audível nenhuma.

A engine te dá as duas funções de conversão, e o padrão é sempre o mesmo: slider trabalha em linear (0.0 a 1.0), bus trabalha em dB, e linear_to_db() faz a ponte.

A API que importa fica toda no singleton AudioServer:

# Buses são acessados por índice, não por nome. Pegue o índice uma vez.
var music_bus := AudioServer.get_bus_index("Music")

AudioServer.set_bus_volume_db(music_bus, -6.0)   # define volume em dB
AudioServer.get_bus_volume_db(music_bus)          # lê o volume atual
AudioServer.set_bus_mute(music_bus, true)         # muta o bus inteiro

O script completo de um slider de volume, do jeito que vai no seu menu de opções (HSlider com min_value = 0.0, max_value = 1.0, step = 0.01):

extends HSlider

@export var bus_name := "Music"

@onready var bus_index := AudioServer.get_bus_index(bus_name)

func _ready() -> void:
    # Inicia o slider na posição que reflete o volume atual do bus.
    value = db_to_linear(AudioServer.get_bus_volume_db(bus_index))
    value_changed.connect(_on_value_changed)

func _on_value_changed(new_value: float) -> void:
    AudioServer.set_bus_volume_db(bus_index, linear_to_db(new_value))
    # linear_to_db(0) tende a -infinito; mutar é mais limpo no zero.
    AudioServer.set_bus_mute(bus_index, new_value < 0.001)

Com o @export, o mesmo script serve pros três sliders: você arrasta ele em cada HSlider e só troca o bus_name no Inspector pra "Master", "Music" e "SFX". Sem duplicar código.

Fade de música com Tween

Transição de fase com a música cortando seca denuncia jogo amador. O fade é um tween no volume do bus, e o truque é animar no espaço linear e converter pra dB a cada passo. Se você tweenar o valor em dB direto, o fade soa estranho: passa rápido demais pelo trecho audível e se arrasta no trecho inaudível.

func fade_out_music(duration := 1.5) -> void:
    var bus_index := AudioServer.get_bus_index("Music")
    var from_linear := db_to_linear(AudioServer.get_bus_volume_db(bus_index))
    var tween := create_tween()
    tween.tween_method(
        func(v: float): AudioServer.set_bus_volume_db(bus_index, linear_to_db(v)),
        from_linear,
        0.0001,
        duration
    )

Pro fade in, inverta os valores de origem e destino. E lembre de restaurar o volume do bus antes de tocar a próxima música, senão ela entra muda e você passa vinte minutos caçando um bug que não existe.

Próximo nível
Quer aprender isso na prática?

No CursoGame.Dev você sai dos tutoriais soltos e constrói jogos publicáveis, com trilha progressiva, quests práticas e feedback real.

Conhecer a plataforma
+500 alunos4.9/5Garantia 7 dias

Efeitos de áudio nos buses

Cada bus aceita uma cadeia de efeitos, processados em ordem de cima pra baixo. No painel Audio, clique no slot Add Effect de um bus e escolha da lista: reverb, delay, EQ, compressor, distorção, filtros, limiter e mais. Os efeitos rodam em tempo real sobre tudo que passa pelo bus.

Três usos que aparecem em quase todo projeto:

Reverb pra ambientação. Adicione um AudioEffectReverb no bus SFX (ou num bus dedicado de sons do mundo) e os passos, tiros e impactos ganham o eco do ambiente. Os parâmetros que mais mudam o resultado são room_size e wet (a proporção de som processado na saída). Caverna pede room size alto; sala pequena, baixo. E é por isso que sons de UI merecem bus próprio: clique de botão com reverb de caverna fica esquisito.

Limiter no Master. Um AudioEffectLimiter no fim da cadeia do Master é seguro contra clipping: quando explosão, música e dez efeitos tocam juntos e a soma estoura, o limiter segura o pico antes de virar distorção nos fones do jogador. Custa quase nada e salva o mix nos momentos caóticos.

Low pass no pause. O efeito de "som abafado" quando o menu de pause abre, presente em praticamente todo jogo moderno, é um filtro passa-baixa que corta as frequências agudas. Adicione um AudioEffectLowPassFilter no Master, configure o cutoff_hz pra algo entre 500 e 1000 Hz, e desmarque o checkbox do efeito pra ele começar desligado. Aí é só ligar e desligar por código:

var master_bus := AudioServer.get_bus_index("Master")

func _set_paused(paused: bool) -> void:
    get_tree().paused = paused
    # O low pass é o efeito de índice 0 na cadeia do Master.
    AudioServer.set_bus_effect_enabled(master_bus, 0, paused)

O índice 0 ali é a posição do efeito na cadeia do bus, na ordem em que aparecem no painel. Se você tiver limiter e low pass no mesmo Master, confira qual está em qual posição.

Um aviso sobre pause: AudioStreamPlayer respeita o get_tree().paused por padrão, então a música também congela. Se você quer a música continuando abafada por baixo do menu (que é o efeito gostoso), mude o Process Mode do player da música pra Always no Inspector.

Salvando as configurações de volume

Slider que volta pro padrão toda vez que o jogo abre é o tipo de descuido que o jogador percebe. A persistência é simples com ConfigFile, salvando em user://, que é a pasta de dados do usuário (funciona em desktop, mobile e web sem você pensar em caminho):

extends Node
# Autoload (Project Settings > Globals) chamado AudioSettings.

const SETTINGS_PATH := "user://settings.cfg"
const BUSES := ["Master", "Music", "SFX"]

func _ready() -> void:
    load_volumes()

func save_volumes() -> void:
    var config := ConfigFile.new()
    for bus_name in BUSES:
        var idx := AudioServer.get_bus_index(bus_name)
        config.set_value("audio", bus_name, db_to_linear(AudioServer.get_bus_volume_db(idx)))
    config.save(SETTINGS_PATH)

func load_volumes() -> void:
    var config := ConfigFile.new()
    if config.load(SETTINGS_PATH) != OK:
        return  # primeira execução, sem arquivo ainda: fica nos padrões
    for bus_name in BUSES:
        var idx := AudioServer.get_bus_index(bus_name)
        var linear: float = config.get_value("audio", bus_name, 1.0)
        AudioServer.set_bus_volume_db(idx, linear_to_db(linear))
        AudioServer.set_bus_mute(idx, linear < 0.001)

Registre esse script como autoload e chame AudioSettings.save_volumes() quando o jogador fechar o menu de opções. Note que eu salvo o valor linear, não o dB: é o número que tem significado pro slider, e evita gravar -inf no arquivo quando o volume está zerado.

Erros comuns que valem conferir

Antes de fechar, a lista rápida do que costuma dar errado na prática:

  • Som ignorando o slider: o player está no bus errado (ou o nome do bus mudou e o player caiu de volta no Master). Confira a propriedade Bus do AudioStreamPlayer.
  • Slider que só funciona no finalzinho: você ligou o valor linear direto em set_bus_volume_db sem linear_to_db(). A conversão não é opcional.
  • Música que volta muda depois de um fade out: o volume do bus ficou em -80 dB e ninguém restaurou. Fade é estado, trate como tal.
  • Efeito que não faz nada: ou o checkbox dele está desligado no painel, ou você está mexendo no índice errado da cadeia com set_bus_effect_enabled.

Fechando

Audio bus no Godot é um daqueles sistemas com retorno desproporcional ao esforço: meia hora de setup e o seu jogo ganha sliders de volume de verdade, fade de trilha, mix protegido contra clipping e o abafado de pause que dá cara de produto acabado. A estrutura mínima que eu recomendo pra qualquer projeto é Master, Music e SFX com um limiter no Master, e crescer a partir daí conforme o jogo pedir.

Se quiser fixar, faça o caminho completo num projeto de teste: crie os três buses, roteie um player de música e um de efeito, monte a cena de opções com os três sliders compartilhando o mesmo script, e termine com o low pass no pause. É uma tarde de trabalho e é código que você vai copiar pra todo jogo que fizer daqui pra frente.