今回は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を再生します |