【Godot4.x】インタラクティブミュージックの使い方

今回はGodot4.3以降で追加されたインタラクティブミュージックの使い方を説明します。

インタラクティブミュージックとは

インタラクティブミュージックを簡単に定義すると、ゲームとの相互作用によって変化するBGMのことです。 具体的には、RPGにおいて街にいる場合は賑やかなBGM、草原を歩いているときは穏やかなBGM、戦闘に入ると勇ましいBGMになる、といったシーンの変化に伴うBGMの変化のことです。 ただこれらは広い意味でのインタラクティブミュージックで、狭義では、シーンやプレイヤーの状況によって「シームレス」にBGMが切り替わることを指します。

この「シームレス」なBGM変化というのは「横の変化」と「縦の変化」があります。

手法 概要 具体例 対応するGodotのリソース
横の変化 シーンや状況の変化に合わせて、
曲そのものが滑らかにつながる
フィールド曲からバトル曲への変化 AudioStreamPlaylist
AudioStreamInteractive
縦の変化 シーンや状況の変化に合わせて、
曲の一部や構成が入れ替わる
同じメロディで楽器だけが入れ替わる
ドラムなどのパート入ったりミュートする
AudioStreamSynchronized

Godotでのインタラクティブミュージックのリソースの位置づけ

Godotのサウンド管理におけるインタラクティブミュージックのリソースとして位置づけについて図にしてみました。

これは公式の定義ではなく個人的な定義ですが、上記の図の中で「特殊リソース」に当たるのがインタラクティブミュージックを行うリソースです。 そしてこのリソースはサウンドリソースの一部なので、WAVやMP3といったオーディオデータと同様に AudioStreamPlayerで再生することが可能です。

リソースの作成方法

インタラクティブミュージックに関するリソースを作成するにはGodot Engineのファイルシステムを右クリックして「+新規作成 > リソース」を選びます。

そして「audiostream」で検索すると各リソースが見つかります。

各リソースの説明

AudioStreamPlaylist (プレイリスト再生)

AudioStreamPlaylistは、音楽アプリによくあるプレイリストのようなものです。 これはゲームの変化に伴って切り替えるというよりは、ジュークボックスのようにランダムで再生されるBGMのリストを登録して使う用途になると思います。

上記のように複数のオーディオデータを登録し、それを上から順番に再生します。 再生オプションとして以下のものがあります。

  • Shuffle: ランダムな順番で再生
  • Loop: プレイリストに含まれる曲をすべて再生した後のループ設定
  • Fade Time: 次の曲に変わるときのクロスフェード時間

AudioStreamSynchronized (ステム再生)

AudioStreamSynchronizedは、複数のオーディオデータを同時に再生して必要に応じてそれらをON/OFFできます。 「縦の変化」を行うBGMに使います。

ただし Godot4.4の時点では自動でフェードする機能は用意されていないため、以下のようなフェード処理を自作する必要があります。

@onready var stem_player = $StemPlayer # AudioStreamPlayer2D
@onready var stem_sync = stem_player.stream as AudioStreamSynchronized

enum eStem {
    DRUM_BASS = 0,
    DRUM2 = 1,
    LEAD = 2,
}

# レイヤーごとの音量を「線形ゲインでフェード」→ 設定時に dB へ変換
func set_layer_db(i: eStem, db_target: float, t := 2.0):
    if stem_sync == null:
        return

    # 現在値(dB)→ 線形へ
    var db_from := 0.0
    if stem_sync.has_method("get_sync_stream_volume"):
        db_from = stem_sync.get_sync_stream_volume(i)

    var lin_from := db_to_linear(db_from)
    var lin_to   := db_to_linear(db_target)

    # 0 は -inf dB になってしまうので小さな値で下駄を履かせる
    const EPS := 1e-5
    lin_from = max(lin_from, EPS)
    lin_to   = max(lin_to,   EPS)

    var tw := get_tree().create_tween()
    tw.tween_method(
        func(lin):
            # 補間は線形ゲイン、設定は dB
            var db := linear_to_db(max(lin, EPS))
            stem_sync.set_sync_stream_volume(i, db),
        lin_from, lin_to, t
    )

AudioStreamInteractive (インタラクティブミュージック)

AudioStreamInteractive は最も複雑なBGMの遷移を可能とします。 使い方としては、他のサウンドリソースと同様にオーディオデータを登録。

そしてインスペクタの一番下にある「トランジションの編集」をクリック。

トランジションエディタが表示されます。

トランジションエディタは表形式の入力となっていて、縦軸が「遷移元」横軸が「遷移先」となっています。

例えば上記の枠には "BGM_01" から "BGM_02" の遷移のルールを指定します。 まずは対象のセルをクリック。

トランジションを有効にして、以下のように設定します。

項目 説明
トランジション 有効 これを有効にしないと遷移時の処理は無効となります
遷移元 次の小節 次の曲に移行するタイミング
フェード拍数 4.0 4拍子であれば1小節かけてクロスフェードします

シーンには以下のようにノードを配置してみました。

各ボタンでBGMを切り替えるものとします。 そして AudioStreamPlayer2Dは以下のようにしました。

  • Stream: AudioStreamInteractiveリソースを設定
  • Autoplay: オンにして自動再生

スクリプトは以下のようにしました。

extends Node2D

@onready var player = $AudioStreamPlayer2D

func _on_button_01_pressed() -> void:
    # Bam_01に切り替え
    player.set("parameters/switch_to_clip", "Bgm_01")

func _on_button_02_pressed() -> void:
    # Bam_02に切り替え
    player.set("parameters/switch_to_clip", "Bgm_02")

func _on_button_03_pressed() -> void:
    # Bam_03に切り替え
    player.set("parameters/switch_to_clip", "Bgm_03")

AudioStreamInteractiveで曲を切り替える場合、"parameters/switch_to_clip" という特殊なキーでオーディオリソース名を渡します。オーディオリソース名は大文字・小文字を間違えると再生されないことに注意します。

実行して、"Bgm_01" から "Bgm_02" へ遷移するときに、1小節かけてクロースフェード再生することを確認します。

トランジションのパラメータの説明

AudioStreamInteractiveのトランジションで指定可能なパラメータの説明をまとめておきます。

項目 パラメータ 説明
遷移元 即座 次の曲に即座に切り替えます
次の拍 現在の曲の次の拍で、次の曲に切り替えます
次の小節 現在の曲の次の小節で、次の曲に切り替えます
クリップ終了 現在の曲の終端で、次の曲に切り替えます
遷移先 同じ位置 現在の曲の位置と同じところから再生します
クリップ開始 曲の先頭から再生
前の位置 前回停止した位置から再生
フェードモード 無効 フェードなし
フェードイン 現在の曲を停止し、次の曲をフェードインしながら次の曲を再生します
フェードアウト 現在の曲をフェードアウトし、次の曲を再生します
クロスフェード 現在の曲をフェードアウト、次の曲をフェードイン
自動設定 フェード拍数に合わせて自動でフェード
補間クリップ 無効 補間クリップを使用しない
クリップ名 次の曲に遷移する前に再生するクリップを指定します。
補間クリップの再生完了後に次の曲に遷移します|
前を保持 ON/OFF ONにすると、次に再生するときに
停止した位置の続きからBGMを再生します