BGMマネージャー構築★

絶対調味ロジック

少し前にBGM再生を任意タイミングにする改善をしました。
音量設定の構築★【Unity6】- BGM任意タイミング再生★

しかし、ノベル演出をしていくうちに、さらなる機能が必要になってきたので、
BGM全体を制御できるシステムをシンプルにまとめてしまおうと画策しました。

機能としては、
・使用BGMのデータベース化
・VolumeScale(素材の音量)の調整を可能に
・任意のタイミングでの再生開始もしくは停止
・任意のタイミングでのBGM切り替え
・セーブロード対応

任意タイミングは手動で設置するため、自動化は無理でしたが、データベース化はできたので扱いやすくなりました。

概要と基本設計方針

Unity6 (6000.3.10) URP 環境およびロースペックPCでの動作を念頭に置いた、軽量・堅牢なBGM管理システム。

  • 永続化マネージャー(DDOL):Sys_BGMManager が音源再生・フェードを同一箇所で一括管理。
  • データ主導管理(ScriptableObject):曲ファイルや個別音量は SO_BGMDataBase で一元管理。
  • トリガー制御:演出用カットやマップオブジェクトには Cmd_PlayBGM をアタッチし、
    アクティブ化(OnEnable)に応じて再生・停止命令を発行。
  • セーブ&ロード完全対応:
    • ノベルパート:遡り再生中に通過した最後の bgmID を軽量なメモリ(static 変数)に保持し、復元後に再生。
    • 探索パート:復元されたアクティブな Location 配下の Cmd_PlayBGM を検知して再生。

各コンポーネントの実装

SO_BGMDataBase.cs (データベース)

各曲の ID、AudioClip、個別音量調整、ループ設定を定義します。

Sys_BGMManager.cs (マネージャー機能)

シーンを跨いで存在する Singleton + DontDestroyOnLoad オブジェクトです。
・アタッチすると自動で「AudioSource」も追加されます。
・SO_BGMDataBase.cs (データベース)をアサインしておきます。

Cmd_PlayBGM.cs (再生・停止コマンド)

CutやLocationオブジェクト等に配置し、演出上のBGM制御を行います。
・CommandTypeタブで「Play」「Stop」を指定できます。
・BGM IDでデータベースのBGMを指定します。
・開始や停止の動作にフェードを付与できます。

Sys_SaveManager.cs (ロード連携の該当処理)

LoadRoutine コルーチンの先頭と末尾にBGM制御を追加しています。

IEnumerator LoadRoutine(SaveData data)
    {
        UI_Manager.Instance?.CloseAll();

        // ★ 1. ロード開始処理:誤作動防止のメモリ初期化と旧BGMのフェードアウト停止
        Cmd_PlayBGM.LastLoadedBGMID = "";
        Sys_BGMManager.Instance?.StopBGM(0.3f);

        Sys_FadeManager.Instance.FadeOut();

        Sys_CutManager.WillLoadFromSave = true;
        IsLoading = true;

        // --- (中略:シーンロード、フラグ復元、ノベル遡り再生、探索復元処理) ---

        yield return new WaitForSeconds(Sys_FadeManager.Instance.displayTime);

        // ★ 2. ロード完了処理:ガード解除とBGM復元
        IsLoading = false;

        // A. ノベルパート:遡り再生で記憶したBGMがあれば再生
        if (!string.IsNullOrEmpty(Cmd_PlayBGM.LastLoadedBGMID))
        {
            Sys_BGMManager.Instance?.PlayBGM(Cmd_PlayBGM.LastLoadedBGMID, Cmd_PlayBGM.LastLoadedFadeDuration);
        }
        // B. 探索パート:アクティブ化された Location 配下の Cmd_PlayBGM を実行
        else
        {
            Cmd_PlayBGM activeBGM = FindFirstObjectByType<Cmd_PlayBGM>();
            if (activeBGM != null && activeBGM.gameObject.activeInHierarchy)
            {
                activeBGM.ExecuteCommand();
            }
        }

        Sys_FadeManager.Instance.FadeIn();
    }

設定手順および構築ルール

1. Inspectorでの初期設定

Sys_BGMManager(DDOLオブジェクト):
・AudioSourceのAudioClip枠は空(None)のままでOK。
・Play On Awake や Loop の手動チェックは不要(スクリプトが自動設定)。
・Data Base 欄に SO_BGMDataBase アセットをアサイン。

SO_BGMDataBase:
・各曲の Bgm ID(例: “Title”, “Novel”, “Exploration” 等)を設定。
※注意:Volume Scale は必ず 1.0 など適切な音量(0超)を設定(0.0 だと無音再生になります)。

2. ノベルパートでの配置ルール

・BGMを変更・再生したい Cut オブジェクト配下の空GameObjectに Cmd_PlayBGM をアタッチ。
・Command Type を Play に設定し、Bgm ID を入力。
全Cutに置く必要はありません。 遡り再生により、次回ロード時には自動的に直近のBGMが復元されます。
・演出でBGMを止めたいCutには Cmd_PlayBGM を置き、Command Type を Stop に設定。

3. 探索パート(Location)での配置ルール

・各 Sys_LocationController(5つのロケーション等)配下にそれぞれ Cmd_PlayBGM を1つずつ配置。
・これにより今後ロケーションごとに異なるBGMを設定する場合でも、それぞれの Location オブジェクト配下に置くだけで自動対応可能です。

注意事項およびトラブルシューティング

  • Bgm ID の完全一致:
    Cmd_PlayBGM に設定する Bgm ID 文字列は、
    SO_BGMDataBase に登録した ID と大文字・小文字・スペース含めて完全一致させてください。
  • タイトル画面など Cut が無いシーン:
    初期化用オブジェクト等に Cmd_PlayBGM を配置してBGMを発火させてください。
  • ロード中に音が鳴らない/重い場合:
    Sys_SaveManager.IsLoading ガードにより、ロード完了(暗転明け)まで音は鳴らない仕様です。
    処理負荷をかけずロースペック端末でも安定して動作します。

イコライザー対応修正★0821

■ 実装の概要と修正の経緯

課題:
Sys_BGMManager の新規導入に伴い、BGMの AudioSource がマネージャー内部へ集約されたため、従来の SingleAudioSource 直参照を行っていた Sys_AudioVisualizerTiled の反応が消失した。

解決策:
・Sys_BGMManager 側で波形参照用の AudioSource を公開(getterのみ)。
・Sys_AudioVisualizerTiled に BGMManager 用の取得ルートを新設し、シングルトン経由で動的に波形データを取得する構成へ変更。

■ 各コンポーネントの役割と設定値

Sys_BGMManager(BGM管理)
役割:ゲーム全体のBGM再生・フェード・ループを一括管理する。
公開プロパティ:AudioSource 外部(イコライザー等)から再生中の波形データを取得するための読み取り専用参照。

Sys_AudioVisualizerTiled(UIイコライザー)
TargetType(監視対象の切り替え):
・BGMManager:Sys_BGMManager.Instance.AudioSource からBGMの波形を取得(BGM用)。
・SEManager:Sys_AudioManager から全体のSE再生レベルを取得(SE用)。
・SingleAudioSource:ボイス再生用 AudioSource 等の単体ソースを監視(ボイス等用)。
ChannelType(ミュート・音量連動):
Sys_AudioSettingsManager と連動し、対象チャンネルがミュートまたは音量 0 の場合に自動でメーター描画を停止する。

■ 新規構築・再設定の手順

1. スクリプトの適用
・Sys_BGMManager.cs に public AudioSource AudioSource => audioSource; が定義されていることを確認する。
・Sys_AudioVisualizerTiled.cs に TargetType.BGMManager の分岐処理が記述されていることを確認する。

2. Inspector(Unityエディタ)での設定
BGM用イコライザーオブジェクト:
・Target Type:BGMManager に設定
・Channel Type:BGM に設定
ボイス用イコライザーオブジェクト:
・Target Type:SingleAudioSource に設定
・Channel Type:Voice に設定

■ 動作特性と注意点

  • Sys_BGMManager は DontDestroyOnLoad で動作するため、シーン遷移が発生しても TargetType: BGMManager 側の参照が切れることはありません。
  • 既存のプレハブ破壊を防ぐため、SingleAudioSource の変数名およびEnum定義は従来の名称をそのまま変更せず保持しています。

BGM初期再生不具合の修正★0901

不具合の概要:
ビルド後のアプリ初期起動時において、タイトル画面(最初のScene)のBGMが再生されない。
一度ゲームを開始してタイトルに戻ると再生される。

原因:
・Unityのビルド後環境において、シーン初期化時のコンポーネント実行順序が変化したことによる競合。
・Sys_BGMManager の Awake() (インスタンス生成)よりも先に Cmd_PlayBGM の OnEnable() が実行されてしまい、Sys_BGMManager.Instance == null と判定されて再生命令が消滅していた。
・シーン再訪問時は DontDestroyOnLoad により Instance が残っているため問題が発生しなかった。

実施した改修:
・Cmd_PlayBGM.cs:
OnEnable() 内で Sys_BGMManager.Instance が生成されるまで yield return null で1フレーム待機するコルーチン (WaitForManagerAndExecute) を追加。
・既存機能への配慮:
LastLoadedBGMID への記録や Sys_SaveManager.IsLoading による制御判定は、従来の通り OnEnable 呼び出し時の「即時実行」を維持。

今後の注意点(ナレッジ共有)
・今後、他のシステムコマンドスクリプト(SE再生や画面フェード等)を新規作成する際も、OnEnable や Awake でシングルトンの Instance を直接参照すると同様の順番ズレが発生する可能性があります。
・マネージャー存在チェックを行う場合は、今回と同様に「生成待ち」の安全策を入れるか、Start() 以降のタイミングで参照することを推奨します。

コメント