【Godot】オーディオ管理の基礎 - AudioStreamPlayerとAudio Busを使いこなす

作成: 2025-12-10最終更新: 2026-07-08

GodotのオーディオをAudioStreamPlayerとAudio Busの基礎から解説。音が途切れないSEの鳴らし方、BGM/SE/Voiceのバス分け、AudioManagerシングルトンによる一元管理、スライダー音量制御、リバーブなどのバスエフェクトまで、コードと図で学びます。

BGMや効果音は、同じゲームの手触りをがらりと変える大事な要素です。ところがいざGodotで鳴らしてみると、「効果音を連打すると音がブツ切れになる」「BGMだけ音量を下げたいのにやり方が分からない」「あちこちのスクリプトで音を鳴らしていて管理が破綻する」——といった壁にぶつかりがちです。

これらはすべて、Godotのオーディオの2本柱 AudioStreamPlayer(音を鳴らすノード)Audio Bus(音をまとめる経路) の役割を押さえれば解決できます。この記事では基礎から、AudioManager シングルトンによる実践的な一元管理までを組み立てます。

青い粘土のスピーカーが音の波紋を広げ、隣に音量フェーダーが並んだミキサーが置かれたオーディオ管理のイメージ

この記事でわかること

  • Godotオーディオの 三大要素(AudioStream / AudioStreamPlayer / Audio Bus)
  • AudioStreamPlayer3種類 の使い分け(無印 / 2D / 3D)
  • 音が途切れない 効果音の鳴らし方(動的生成・max_polyphony
  • AudioManager シングルトンによる 一元管理 とスライダー音量制御
  • Audio Busへの エフェクト適用(リバーブなど)

Sponsored

Godotオーディオの三大要素

Godotで音を鳴らす仕組みは、次の3つの登場人物で理解できます。役割を「音楽を流す機材」にたとえると、すっと入ってきます。

要素役割たとえるなら
AudioStream音声データそのものCDやMP3ファイル
AudioStreamPlayer音を再生するノードCDプレイヤー
Audio Bus音の信号を束ねて制御する経路ミキシングコンソール

音が耳に届くまでの流れは一方向です。 音データ(AudioStream)プレイヤー(AudioStreamPlayer) が鳴らし、その音は バス(Audio Bus) を通り、最終的にすべての音が集まる Masterバス から出力されます。

AudioStream(音データ)→AudioStreamPlayer(鳴らす)→Audio Bus(BGM/SFXの経路)→Master(最終出力)→スピーカーの信号の流れを示した図

この「データ → プレイヤー → バス → Master」という流れさえ頭にあれば、以降の話はすべてこの図のどこかの説明だと分かります。

AudioStreamPlayerの3種類

音を鳴らすノードには3種類あり、 音に「位置」を持たせるかどうか で使い分けます。

AudioStreamPlayer(位置なし・常に中央)、AudioStreamPlayer2D(距離と方向で変化)、AudioStreamPlayer3D(3D空間で距離減衰)の3種類を比較した図
ノード名主な用途特徴
AudioStreamPlayerBGM・UI音など位置情報なし。常に中央から均一に聞こえる
AudioStreamPlayer2D2Dゲームの効果音カメラからの距離・方向で音量とパンが変化
AudioStreamPlayer3D3Dゲームの効果音3D空間での距離減衰・ドップラー効果に対応

使い分けの勘どころはシンプルです。 「画面のどこで鳴っても同じに聞こえてほしい音」(BGM・UIのクリック音)は無印「遠くの敵の足音は小さく、右で爆発したら右から」といった空間を感じさせたい音は2D/3D を選びます。

Sponsored

Audio Busでまとめて制御する

Audio Busは、音の「通り道」であり、ミキシングコンソールのような役割を持ちます。すべての音は最終的に Masterバス に集まりますが、その手前に BGM・SFX・Voice といった自作のバスを用意して、種類ごとに束ねられます。

BGM/SFX/Voiceの3本のフェーダーがMasterフェーダーに合流するミキシングコンソール風の図。バスごとに音量をまとめて調整する

バスを分ける最大のメリットは、 種類ごとに一括制御できる ことです。

  • 音量の一括制御 :「BGMだけ下げる」「SEだけミュート」がバス1本の操作で済む。設定画面の音量スライダーは、この仕組みで作ります
  • エフェクトの一括適用 :リバーブやコンプレッサーを、そのバスを通る全ての音にまとめてかけられる(後述)

バスはエディタ下部の「オーディオ」タブで追加します。各 AudioStreamPlayerbus プロパティに「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 で音を鳴らしている最中に、同じノードで次の音を鳴らすと、前の音が上書きされて途切れる のです。剣を素早く連打すると「シャッ…シャッ」が「シャ、シャ」になる、あれです。

左は1つのノードを使い回して音が途切れる様子、右は再生ごとに動的生成して音が重なって自然に鳴る様子を対比した図

解決策は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つのノードで何個まで同時に鳴らせるかを設定するプロパティで、48 にしておくと、ノードを増やさずに重ね再生できます。UIのクリック音のように「たまに重なる程度」ならこちらが手軽です。

2D/3Dの効果音にしたいとき :位置を持たせたい音は AudioStreamPlayer2D(または3D)を動的生成し、global_position に音源の座標を入れます。

Sponsored

実践:AudioManagerで一元管理する

ここまでの部品を、実際のゲームで最も効くかたちに組み上げましょう。 どのシーンからでも AudioManager.play_bgm(...)AudioManager.play_sfx(...) の一行で音を鳴らせる 、オーディオの管制塔を作ります。

タイトル画面でもバトルでもUIでも、音を鳴らしたい場所は無数にあります。それぞれが個別にプレイヤーを組んでいると管理が破綻するので、 Autoload(シングルトン) で1つの AudioManager に集約 します。

タイトル画面・バトル・UIの3つのシーンがそれぞれplay_bgm()/play_sfx()で中央のAudioManager(Autoload)を呼び、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_dbTween で動かしてフェードします。SEは重なるので 毎回生成して破棄 します。役割が違うので扱いも変えるわけです。
  • 音量はバス経由でまとめて動かすset_bus_volume() にバス名とスライダー値を渡すだけで、設定画面の「BGM音量」「SE音量」スライダーがそのまま作れます。linear_to_db() を挟むのは、スライダーを直線的に動かしても耳に自然な効き方にするためです。
Sponsored

パフォーマンスと代替パターン

大量のSEが同時多発するゲームでは、鳴らし方の選択肢が変わってきます。

アプローチメリットデメリット向いている場面
動的生成(本記事の方式)実装がシンプル大量生成時にノード生成コストほとんどのゲーム
オブジェクトプール生成・破棄のコストが安定実装が複雑毎秒数十〜数百のSEが鳴る弾幕・大量エフェクト

基本は まず動的生成で作り、プロファイラで音まわりがボトルネックと判明したときだけ プールを検討します。プレイヤーを毎回 new() / queue_free() する代わりに、あらかじめ用意したプレイヤーを使い回すのが オブジェクトプーリング です。

Audio Busへのエフェクト適用

バスに エフェクト を追加すると、そのバスを通る 全ての音にまとめて 効果がかかります。SEバスにリバーブを1つ足すだけで、洞窟に入ったときの残響を全効果音に一括で乗せられる——これがバスで束ねる旨みです。

SFXバスにAudioEffectReverbを追加すると、通る音が残響を帯びて尾を引く様子を示した図
  1. エディタ下部の「オーディオ」タブを開く
  2. エフェクトをかけたいバス(例:SFX)を選ぶ
  3. 「エフェクトを追加」から AudioEffectReverb を選択
  4. Room SizeWet(効果の効き具合)を調整

「洞窟エリアでは残響を強め、屋外では弱める」といった演出も、コードから 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ノードの使い回しが原因。動的生成+finishedqueue_free()、または max_polyphony で解決
  • 音量調整 はバス経由。スライダー値は linear_to_db() でデシベルに変換して set_bus_volume_db()
  • エフェクト はバスに足せば、通る音すべてに一括適用

まずは「BGM」「SFX」の2バスを作り、AudioManager から play_bgm() / play_sfx() を鳴らすところから始めてみてください。音まわりが1箇所にまとまると、後からの音量設定やエフェクト追加が一気に楽になります。

さらに学ぶために