BGMや効果音は、同じゲームの手触りをがらりと変える大事な要素です。ところがいざGodotで鳴らしてみると、「効果音を連打すると音がブツ切れになる」「BGMだけ音量を下げたいのにやり方が分からない」「あちこちのスクリプトで音を鳴らしていて管理が破綻する」——といった壁にぶつかりがちです。
これらは すべて、Godotのオーディオの2本柱 AudioStreamPlayer(音を鳴らすノード) と Audio Bus(音をまとめる経路) の役割を押さえれば解決できます。この記事では基礎から、AudioManager シングルトンによる実践的な一元管理までを組み立てます。
この記事でわかること
- Godotオーディオの 三大要素(AudioStream / AudioStreamPlayer / Audio Bus)
AudioStreamPlayerの 3種類 の使い分け(無印 / 2D / 3D)- 音が途切れない 効果音の鳴らし方(動的生成・
max_polyphony)AudioManagerシングルトンによる 一元管理 とスライダー音量制御- Audio Busへの エフェクト適用(リバーブなど)
Godotオーディオの三大要素
Godotで音を鳴らす仕組みは、次の3つの登場人物で理解できます。役割を「音楽を流す機材」にたとえると、すっと入ってきます。
| 要素 | 役割 | たとえるなら |
|---|---|---|
| AudioStream | 音声データそのもの | CDやMP3ファイル |
| AudioStreamPlayer | 音を再生するノード | CDプレイヤー |
| Audio Bus | 音の信号を束ねて制御する経路 | ミキシングコンソール |
音が耳に届くまでの流れは一方向です。 音データ(AudioStream) を プレイヤー(AudioStreamPlayer) が鳴らし、その音は バス(Audio Bus) を通り、最終的にすべての音が集まる Masterバス から出力されます。

この「データ → プレイヤー → バス → Master」という流れさえ頭にあれば、以降の話はすべてこの図のどこかの説明だと分かります。
AudioStreamPlayerの3種類
音を鳴らすノードには3種類あり、 音に「位置」を持たせるかどうか で使い分けます。

| ノード名 | 主な用途 | 特徴 |
|---|---|---|
AudioStreamPlayer | BGM・UI音など | 位置情報なし。常に中央から均一に聞こえる |
AudioStreamPlayer2D | 2Dゲームの効果音 | カメラからの距離・方向で音量とパンが変化 |
AudioStreamPlayer3D | 3Dゲームの効果音 | 3D空間での距離減衰・ドップラー効果に対応 |
使い分けの勘どころはシンプルです。 「画面のどこで鳴っても同じに聞こえてほしい音」(BGM・UIのクリック音)は無印 、 「遠くの敵の足音は小さく、右で爆発したら右から」といった空間を感じさせたい音は2D/3D を選びます。
Audio Busでまとめて制御する
Audio Busは、音の「通り道」であり、ミキシングコンソールのような役割を持ちます。すべての音は最終的に Masterバス に集まりますが、その手前に BGM・SFX・Voice といった自作のバスを用意して、種類ごとに束ねられます。

バスを分ける最大のメリットは、 種類ごとに一括制御できる ことです。
- 音量の一括制御 :「BGMだけ下げる」「SEだけミュート」がバス1本の操作で済む。設定画面の音量スライダーは、この仕組みで作ります
- エフェクトの一括適用 :リバーブやコンプレッサーを、そのバスを通る全ての音にまとめてかけられる(後述)
バスはエディタ下部の「オーディオ」タブで追加します。各 AudioStreamPlayer の bus プロパティに「SFX」などバス 名を指定すれば、その音はそのバスを通るようになります。コードからバスを扱うときは、 インデックスを直書きせず名前から取得 するのが鉄則です。
# NG: インデックス直書きは、バスの並び替えで壊れる
AudioServer.set_bus_volume_db(1, -10.0)
# OK: バス名からインデックスを取得する
var sfx_index := AudioServer.get_bus_index("SFX")
AudioServer.set_bus_volume_db(sfx_index, -10.0)
効果音が途切れない鳴らし方
初心者が最初につまずくのが「効果音のブツ切れ」です。原因ははっきりしています。 1つの AudioStreamPlayer で音を鳴らしている最中に、同じノードで次の音を鳴らすと、前の音が上書きされて途切れる のです。剣を素早く連打すると「シャッ…シャッ」が「シャ、シャ」になる、あれです。

解決策は2つあります。まず定番は、 再生のたびにプレイヤーを動的生成し、鳴らし終わったら自分で消える 方式です。
# 再生ごとにノードを作り、終わったら破棄する
func play_sfx(stream: AudioStream) -> void:
var player := AudioStreamPlayer.new()
player.stream = stream
player.bus = "SFX" # SFXバスに通す
add_child(player)
player.play()
player.finished.connect(player.queue_free) # 再生が終わったら自分を削除
finished シグナルは音の再生が終わった瞬間に飛ぶので、そこで queue_free() すれば、鳴り終わった音のノードが自動で片付きます。連打しても1発ごとに別ノードが生まれるので、音が重なって自然に鳴ります。
もう1つは、 max_polyphony(同時発音数)を上げる 方法です。1つのノードで何個まで同時に鳴らせるかを設定するプロパティで、4〜8 にしておくと、ノードを増やさずに重ね再生できます。UIのクリック音のように「たまに重なる程度」ならこちらが手軽です。
2D/3Dの効果音にしたいとき :位置を持たせたい音は
AudioStreamPlayer2D(または3D)を動的生成し、global_positionに音源の座標を入れます。
実践:AudioManagerで一元管理する
ここまでの部品を、実際のゲームで最も効くかたちに組み上げましょう。 どのシーンからでも AudioManager.play_bgm(...) や AudioManager.play_sfx(...) の一行で音を鳴らせる 、オーディオの管制塔を作ります。
タイトル画面でもバトルでもUIでも、音を鳴らしたい場所は無数にあります。それぞれが個別にプレイヤーを組んでいると管理が破綻するので、 Autoload(シングルトン) で1つの AudioManager に集約 します。

プロジェクト設定の「AutoLoad」タブで AudioManager.gd を登録すると、全シーンから AudioManager の名前でアクセスできます。
extends Node
const BGM_BUS = "BGM"
const SFX_BUS = "SFX"
var bgm_player: AudioStreamPlayer
func _ready() -> void:
# バスが見つからなければ早めに気づけるようにチェック
if AudioServer.get_bus_index(BGM_BUS) == -1:
push_error("Audio Bus '%s' が見つかりません" % BGM_BUS)
# BGMを再生(フェードイン付き)
func play_bgm(stream: AudioStream, fade_in := 0.5) -> void:
if not bgm_player: # BGM用プレイヤーは1つだけ使い回す
bgm_player = AudioStreamPlayer.new()
bgm_player.bus = BGM_BUS
add_child(bgm_player)
bgm_player.stream = stream
bgm_player.volume_db = -80.0 # 一旦ほぼ無音から
bgm_player.play()
# Tweenで音量を0dB(等倍)まで持ち上げ、じわっと立ち上げる
create_tween().tween_property(bgm_player, "volume_db", 0.0, fade_in)
# 効果音を再生(毎回ノードを生成して破棄)
func play_sfx(stream: AudioStream) -> void:
var player := AudioStreamPlayer.new()
player.stream = stream
player.bus = SFX_BUS
add_child(player)
player.play()
player.finished.connect(player.queue_free)
# スライダー(0.0〜1.0)からバス音量を設定
func set_bus_volume(bus_name: String, linear: float) -> void:
var index := AudioServer.get_bus_index(bus_name)
if index == -1:
return
# 人間の音量感覚は対数的。linear_to_db()でデシベルに変換して渡す
AudioServer.set_bus_volume_db(index, linear_to_db(clampf(linear, 0.0, 1.0)))
呼び出し側は、鳴らしたい場所でこう書くだけです。
const JUMP_SFX = preload("res://assets/sfx/jump.ogg")
func _on_jump() -> void:
AudioManager.play_sfx(JUMP_SFX) # どのシーンからでも一行
ポイントは2つです。
- BGMとSEで戦略を変えている :BGMは同時に1曲なので プレイヤーを1つ使い回し、
volume_dbを Tween で動かしてフェードします。SEは重なるので 毎回生成して破棄 します。役割が違うので扱いも変えるわけです。 - 音量はバス経由でまとめて動かす :
set_bus_volume()にバス名とスライダー値を渡すだけで、設定画面の「BGM音量」「SE音量」スライダーがそのまま作れます。linear_to_db()を挟むのは、スライダーを直線的に動かしても耳に自然な効き方にするためです。
パフォーマンスと代替パターン
大量のSEが同時多発するゲームでは、鳴らし方の選択肢が変わってきます。
| アプローチ | メリット | デメリット | 向いている場面 |
|---|---|---|---|
| 動的生成(本記事の方式) | 実装がシンプル | 大量生成時にノード生成コスト | ほとんどのゲーム |
| オブジェクトプール | 生成・破棄のコストが安定 | 実装が複雑 | 毎秒数十〜数百のSEが鳴る弾幕・大量エフェクト |
基本は まず動的生成で作り、プロファイラで音まわりがボトルネックと判明したときだけ プールを検討します。プレイヤーを毎回 new() / queue_free() する代わりに、あらかじめ用意したプレイヤーを使い回すのが オブジェクトプーリング です。
Audio Busへのエフェクト適用
バスに エフェクト を追加すると、そのバスを通る 全ての音にまとめて 効果がかかります。SEバスにリバーブを1つ足すだけで、洞窟に入ったときの残響を全効果音に一括で乗せられる——これがバスで束ねる旨みです。

- エディタ下部の「オーディオ」タブを開く
- エフェクトをかけたいバス(例:
SFX)を選ぶ - 「エフェクトを追加」から
AudioEffectReverbを選択 Room SizeやWet(効果の効き具合)を調整
「洞窟エリアでは残響を強め、屋外では弱める」といった演出も、コードから Wet を動かせば動的に切り替えられます。リバーブ以外にも、コンプレッサー・EQ・ローパスなど、実機のエフェクターと同じ発想のものが一通り揃っています。
おまけ:先に知っておくと良いこと
基礎が組めたら、次はこのあたりが待っています。今すぐ全部覚える必要はありません。
- バス設定を保存する :作ったバス構成は
audio_bus_layout.tresに保存し、プロジェクト設定の「Audio > Buses > Default Bus Layout」で指定します。これを忘れると起動時に「Bus not found」になりがちです。 - BGMをループさせる :
.oggなどのインポート設定で「Loop」を有効にすると、BGMが途切れず繰り返します。ループ位置を細かく指定したいときはインポート設定の出番です。 - エフェクトを深掘りする :EQ → Compressor → Limiter とバスにエフェクトを重ねる「エフェクトチェーン」は AudioBusエフェクトでサウンドデザイン で扱います。
- 空間音響を極める :足音の距離感やドップラーなど、3Dの音づくりは 3Dオーディオと空間音響 へ。
- 場面で曲を変える :戦闘の激しさに合わせてBGMを切り替える仕組みは アダプティブミュージック が入口です。
まとめ
| 概念 | 役割 | ベストプラクティス |
|---|---|---|
| AudioStreamPlayer | 音を鳴らすノード | SEは動的生成で途切れ防止、BGMは1つ使い回してフェード |
| Audio Bus | 音をまとめる経路・ミキサー | BGM/SFX/Voiceで分け、名前からindexを取得 |
| AudioManager | 全体の管制塔 | Autoloadで一元管理し、一行で鳴らす |
- 音が途切れる のは1ノードの使い回しが原因。動的生成+
finished→queue_free()、またはmax_polyphonyで解決 - 音量調整 はバス経由。スライダー値は
linear_to_db()でデシベルに変換してset_bus_volume_db() - エフェクト はバスに足せば、通る音すべてに一括適用
まずは「BGM」「SFX」の2バスを作り、AudioManager から play_bgm() / play_sfx() を鳴らすところから始めてみてください。音まわりが1箇所にまとまると、後からの音量設定やエフェクト追加が一気に楽になります。
さらに学ぶために
- Autoloadによるシーンをまたぐデータ管理 ——AudioManagerの土台となるシングルトンの作り方
- Tweenで実現する滑らかなアニメーション ——BGMのフェードイン/アウトに使う
- シグナルによるノード間の連携 ——
finishedなどのシグナルの仕組み - Object Pooling完全ガイド ——SEを大量に鳴らすときの最適化
- AudioBusエフェクトでサウンドデザイン ——リバーブから一歩進んだエフェクトチェーン
- Godot公式ドキュメント:Audio streams ——AudioStreamPlayerとバスの一次情報