【Godot】3Dオーディオと空間音響 - AudioStreamPlayer3Dで距離と方向を聴かせる

作成: 2026-02-08最終更新: 2026-07-08

GodotのAudioStreamPlayer3Dで3D空間音響を実装する方法を解説。距離減衰モデルの選び方、AudioListener3Dでカメラとリスナーを分離、ドップラー効果、Area3Dのリバーブゾーン、距離フィルタとパフォーマンス最適化まで、コードと図で学びます。

背後から敵の足音が近づいてくる。遠くの爆発が小さく左から聞こえる。洞窟に入った瞬間、音に残響がかかる——3Dゲームの没入感は、こうした 「音がどこから、どれくらいの距離で鳴っているか」 の表現で大きく変わります。

Godotではこれを AudioStreamPlayer3D が引き受けてくれます。音源に位置を持たせるだけで、リスナー(通常はカメラ)との距離と方向に応じて、音量とステレオの左右(パン)が自動で変わります。この記事では、その基本設定から減衰モデルの選び方、リスナーの分離、ドップラー効果、エリアごとの残響までを組み立てます。

3Dのグリッド床に置いたスピーカーから音の波紋が球状に広がり、離れた場所のリスナー人形に届く3Dオーディオのイメージ

この記事でわかること

  • AudioStreamPlayer3D の基本—— 距離で音量、方向でパンが自動変化
  • シーン規模で選ぶ 減衰モデル(Inverse / Square / Log / Disabled)
  • AudioListener3Dカメラとリスナーを分離 する(TPS・カットシーン)
  • ドップラー効果Area3Dのリバーブゾーン
  • 距離で こもらせる フィルタと、大量音源の パフォーマンス最適化

Sponsored

AudioStreamPlayer3Dの基本

AudioStreamPlayer3D は、 3D空間内で位置を持つ 音声再生ノードです。リスナー(通常は current = true のCamera3D)との 距離 に応じて音量が、 方向 に応じてステレオの左右(パン)が自動で変わります。「右奥から敵の声」「真後ろで爆発」といった定位が、位置を置くだけで作れます。

リスナー人形に対し、近い音源は大きく右から、遠い音源は小さく左から届く様子を示した図。距離で音量、方向で左右のパンが変わる

音の届き方を決める主要プロパティはこのあたりです。

プロパティ説明既定値
unit_size音量が半分になる距離。 実質の"聞こえる範囲"を決める10.0
max_distanceこれより遠いと完全に無音になる距離(0=無制限)0
attenuation_model距離による減衰の計算方式(後述)Inverse Distance
panning_strength左右パンの強さ1.0
emission_angle_enabled指向性(特定方向へ強く飛ばす)false

敵の足音を鳴らす基本形はこうです。

# Enemy (CharacterBody3D)
#   └── FootstepSound (AudioStreamPlayer3D)
@onready var footstep: AudioStreamPlayer3D = $FootstepSound

func _ready() -> void:
    footstep.stream = preload("res://audio/sfx/footstep.ogg")
    footstep.unit_size = 5.0       # 5mで音量が半分=そこそこ近くでよく聞こえる
    footstep.max_distance = 30.0   # 30mより遠いと無音(無駄な計算を切る)
    footstep.bus = "SFX"           # SFXバスに通す

func play_footstep() -> void:
    if not footstep.playing:       # 多重再生を避ける
        footstep.play()

unit_size が「聞こえる範囲」の体感を決めるつまみです。 監視カメラの警告音やスピーカー放送のように「特定方向にだけ飛ばしたい」 ときは、emission_angle_enabled = true にして emission_angle_degrees で角度を絞ります。

減衰モデルの選択

attenuation_model は、 距離が離れるにつれ音量がどんな曲線で下がるか を決めます。リアルさを取るか、ゲームの聞き取りやすさを取るかで選びます。

距離と音量の関係を4つの減衰カーブで比較したグラフ。Inverse Distanceは緩やか、Inverse Squareは急、Logarithmicは中間、Disabledは減衰なし
モデル減衰向いているシーン
Inverse Distance距離に反比例(緩やか)屋外の広いフィールド
Inverse Square距離の2乗に反比例(現実的で急)リアル志向のゲーム
Logarithmic対数的(人間の聴覚に近い)室内・近距離のやり取り
Disabled減衰なし(一定)BGM的な環境音・アンビエント
footstep.attenuation_model = AudioStreamPlayer3D.ATTENUATION_INVERSE_SQUARE_DISTANCE

# unit_size と max_distance の目安(シーン規模ごと)
# 小さい部屋 : unit_size=2.0,  max_distance=10.0
# 中規模屋内 : unit_size=5.0,  max_distance=25.0
# 屋外フィールド: unit_size=10.0, max_distance=50.0

迷ったら Inverse Square(現実的) を基準に、聞こえづらければ unit_size を大きくして調整するのが手堅い進め方です。

Sponsored

AudioListener3Dでリスナーを分離する

既定では「カメラのいる場所」で音を聴きます。ところが 三人称視点(TPS)でカメラを大きく引く と、カメラ位置とプレイヤー位置がずれ、「自分のすぐ横の物音が遠く聞こえる」違和感が生まれます。

そこで AudioListener3Dプレイヤーの子 に置いて有効化すると、カメラがどこにあっても プレイヤーの位置を基準に 音が聴こえるようになります。

三人称視点でカメラは後方に引いているが、聴取点(Listener)はプレイヤーの頭部にあり、近くの音源はプレイヤー位置で聴こえる図
パターンリスナー用途
一般的なゲームCamera3D(既定)カメラ位置=聴取位置でよい
TPS(三人称)AudioListener3D引いたカメラでもプレイヤー付近の音を聴かせる
カットシーンAudioListener3Dカメラが動いてもプレイヤー基準を保つ
# Player (CharacterBody3D)
#   └── AudioListener3D
@onready var listener: AudioListener3D = $AudioListener3D

func _ready() -> void:
    listener.make_current()  # このリスナーを有効化(カメラより優先される)

make_current() を呼んだ瞬間から、聴取点がここに移ります。カットシーンだけ一時的にカメラへ戻したいなら clear_current() で解除できます。

ドップラー効果

すれ違う車、通り過ぎる救急車——動く音源が近づくと音程が上がり、遠ざかると下がる。この ドップラー効果 も、プロパティ1つで有効化できます。

リスナーの前を車が右へ通り過ぎる図。近づく側は音波が詰まって高い音、離れる側は音波が広がって低い音になる
# 音源とリスナー(Camera3D)の両方でドップラー追跡を有効にする
$AudioStreamPlayer3D.doppler_tracking = AudioStreamPlayer3D.DOPPLER_TRACKING_PHYSICS_STEP

# トラッキングモード
# DOPPLER_TRACKING_DISABLED     … 無効(既定)
# DOPPLER_TRACKING_IDLE_STEP    … _process()に同期
# DOPPLER_TRACKING_PHYSICS_STEP … _physics_process()に同期(高速移動でも安定)

ドップラーは 音源の速度から計算 されるため、高速に動くオブジェクトでは物理と同期する PHYSICS_STEP が安定します(_processと_physics_processの使い分け も参考に)。使いどころはレースゲーム・弾丸・乗り物などに絞るのがおすすめです。常時オンだと計算が増えます。

Sponsored

Area3Dのリバーブゾーン

「洞窟に入った瞬間、音が反響する」——空間ごとの残響は、Area3Dリバーブゾーン 機能で自動化できます。AudioBusエフェクト の記事では手動でリバーブを付け外ししましたが、こちらは エリアに入ったら自動で 専用バスへ切り替わる仕組みです。

点線で囲まれたArea3Dのゾーン(洞窟)の中では音が長く反響し、外ではすっきり聞こえる図。ゾーンの中では自動でリバーブに切り替わる

Area3DCollisionShape3D で範囲を作り、リバーブ用バスを指定します。

func setup_reverb_zone() -> void:
    var area := $ReverbZone as Area3D
    area.reverb_bus_enabled = true          # このエリアのリバーブを有効化
    area.reverb_bus_name = &"CaveReverb"    # 送り先のリバーブバス
    area.reverb_bus_amount = 0.6            # どれだけリバーブ側へ送るか
    area.reverb_bus_uniformity = 0.8        # エリア内でのかかり方の均一さ

送り先の CaveReverb バスには、あらかじめ AudioEffectReverbroom_size: 0.85 / wet: 0.4 など)を追加しておきます。プレイヤーが範囲に入ると、範囲内の音が自動でこのバスへ送られ、残響がかかります。エリアを出れば自動で戻る——出入りのコードを書かずに済むのが利点です。

距離でこもらせる+パフォーマンス

さらにリアルにするなら、 遠くの音の高音を削って「こもらせる」 と距離感が増します。近い音はクリアに、遠い音はモゴモゴと——これはローパスフィルタ用のプロパティで作れます。

近い音源はクリアな高音を含む波形、遠い音源は高音が削れて丸くこもった波形になる対比図。距離でローパスをかけると距離感が出る
extends AudioStreamPlayer3D

@export var listener_node: Node3D
@export var far_distance: float = 30.0

func _process(_delta: float) -> void:
    if not listener_node:
        return
    var dist := global_position.distance_to(listener_node.global_position)
    var ratio := clampf(dist / far_distance, 0.0, 1.0)
    # 遠いほど高音の上限を下げる(20500Hz→2000Hz)=こもる
    attenuation_filter_cutoff_hz = lerpf(20500.0, 2000.0, ratio)

パフォーマンス最適化

オープンワールドのように音源が大量にあると、CPU負荷が問題になります。効くのはこの3つです。

対策説明
max_distance を必ず設定0(無制限)を避け、必要な範囲だけ計算させる
同時再生数を絞るmax_polyphony を1〜4に、同時に鳴るノードは20〜30以下を目安に
遠い音源は止めるリスナーから十分離れたら playing = false で停止(LOD的な間引き)
# リスナーから遠く離れた音源は停止してCPUを節約
func _process(_delta: float) -> void:
    var camera := get_viewport().get_camera_3d()
    if not camera:
        return
    var dist := global_position.distance_to(camera.global_position)
    if dist > max_distance * 1.2 and playing:
        stop()
    elif dist <= max_distance and not playing:
        play()

大量の音源を オブジェクトプーリング 的に管理する発想も、負荷が増えてきたら有効です。

Sponsored

おまけ:先に知っておくと良いこと

  • まずは unit_size で調整 :思ったより聞こえない・聞こえすぎるときは、減衰モデルをいじる前に unit_size を上下させるのが手っ取り早いです。
  • 2Dゲームなら AudioStreamPlayer2D :見下ろし2Dでも「音源からの距離・左右」は表現できます。3Dの考え方はほぼそのまま2Dにも通じます。
  • 環境音は場所ごとにアンビエントを :滝・焚き火・雑踏などは、音源を置いて Disabled 減衰+短い max_distance にすると「そこに近づくと聞こえる」環境音になります。
  • 曲の切り替えはアダプティブミュージックへ :エリアや戦況でBGMを変える演出は アダプティブミュージック の領域です。

まとめ

  • AudioStreamPlayer3D は距離で音量、方向でパンが自動変化。unit_size が聞こえる範囲の体感を決める
  • 減衰モデル はシーン規模で選ぶ(迷ったらInverse Square)。max_distance は必ず設定して無駄な計算を切る
  • AudioListener3D でカメラと聴取点を分離できる(TPS・カットシーンで有効)
  • ドップラーdoppler_trackingPHYSICS_STEP に、Area3D はリバーブゾーンで空間ごとの残響を自動化
  • 最適化max_distance・同時再生数・遠距離の停止が三本柱

まずは敵に AudioStreamPlayer3D で足音を付け、unit_sizemax_distance をいじって「近づくと聞こえる」感覚を確かめてみてください。そこにリスナー分離やエリアリバーブを足すと、世界がぐっと立体的に鳴りだします。

さらに学ぶために