音量設定の構築【Unity6】

絶対調味ロジック

UI画面を構築する上で共通事項はできあがっています。
それを踏まえて、音量設定の設計案をAiに考案してもらいます。

Aiに共通事項や既存スクリプトを確認してもらう資料用として、
Unityで、スクリプトの一括ファイルを作成する方法(AI用コンテキスト生成カスタム)も導入してみましたが、
Aiに添付したら文字数が多すぎて、速攻で使用トークンが枯れたのでお勧めしませんw

重要事項の要約をまとめてもらい、かつ文字数も少なくて済む「NotebookLM」を活用したほうが全然良いです。
API」キーでローカルファイルを指定しない、できない人たちにはこちらがお薦めです。

音量設定の指標

  • 音量の種類
    マスターボリューム
    BGM音量
    SE音量
    システム音量
    ボイス音量(将来的実装を見越して。今回は実装しない)
    マスター音量はすべての音量の基音量。それ以下は、基音量を基準にしての音量調整になるように。
    BGM音量・SE音量・システム音量を分けることは可能なのか。
    可能として、その方法は?専用のフォルダを作成?音素材をラベルなどで識別?
  • 音量管理の仕組み
    業界標準・推奨ということなので「AudioMixer」を使用して構築していきたい。
  • 保存方法
    テキスト設定と同じくSys_フラグ(絶対変数)で永久保存。
  • UI操作感
    スライダーで0〜100の数値調整(テキスト設定と同じ方式):同じく数値表示もつける。
    ミュートボタンをつける。
    プレビュー再生(スライダーを動かすと音が鳴る)をつける:テスト音は制作側が指定可能に。
  • その他、スタンダードで考えて、あると便利・ないと不便・大胆な機能などがあれば提案お願いします。

音量設定の設計案

すべての検証を行い、設計案に移ってもらいます。

AudioMixer構造

Unityエディタ上で、以下のMixerGroupを作成します。

SoundMixer (AudioMixer)
 └── Master (MixerGroup)
     ├── BGM (MixerGroup)
     ├── SE (MixerGroup)
     └── Voice (MixerGroup)

Exposed Parametersとして以下の4つを公開します。名前はコードから参照するため正確に定めます。
MasterVolume“ ”BGMVolume“ ”SEVolume“ ”VoiceVolume

新規スクリプト構成

Sys_AudioSettingsManager.cs

・音量・ミュートの値管理
・AudioMixerへのリアルタイム反映
・Close時の一括保存

メソッド構成は Sys_TextSettingsManager と同じパターンに揃えます。

// リアルタイム反映のみ(保存しない)
public void SetVolumeImmediate(ChannelType channel, int value)
public void SetMuteImmediate(ChannelType channel, bool mute)

// Close時に一括保存
public void SaveAll()

// 初期化(デフォルト値書き込み)
private void InitializeDefaults()

UI_AudioSettingsPanel.cs

「UI_PanelBaseを継承します。UI_TextSettingsPanel」と同じ設計パターンです。
Open時にSys_AudioSettingsManagerから現在値を読んでUIに反映、Close時にSaveAll()を呼びます。

スライダーとミュートの連動ロジック

■「マスターボリュームミュート」「ON

・スライダー調整でもミュートは解除されない
・表示:BGM・SE・Voice「ミュート」「ON」
・機能:子のミュートボタン操作不可・スライダー操作不可

■ 「BGM」「SE」「Voice」→「ミュート」「ON

・スライダー調整でもミュートは解除されない

プレビュー再生

・BGMはリアルタイム調整
・SE・Voiceはdelay方式ワンショット再生
・スライダーが動くたびにCoroutineをキャンセル&再起動

「初期設定に戻す」ボタン

UIパネル側のボタンから呼び出し後、スライダーとミュートボタンの表示をRefreshAll()で更新。

Hierarchy構造

[Scene Root]
 │
 ├── [Persistent] ← DontDestroyOnLoadで生き続けるオブジェクト群
 │   ├── Sys_Flag_Manager
 │   ├── Sys_TextSettingsManager
 │   └── Sys_AudioSettingsManager ← 今回追加
 │   └── (AudioMixerをInspectorでアサイン)
 │
 └── UI_Root (Canvas)
     ├── UI_SaveLoadPanel
     ├── UI_TextSettingsPanel
     └── UI_AudioSettingsPanel ← 今回追加
         └── Panel (GameObject, 初期非表示)
             ├── CloseButton
             ├── ResetButton
             │
             ├── Master_Section
             │    ├── Label (“マスター”)
             │    ├── Slider_Master
             │    ├── Text_Master (数値表示)
             │    └── MuteButton_Master
             │
             ├── BGM_Section
             │    ├── Label (“BGM”)
             │    ├── Slider_BGM
             │    ├── Text_BGM
             │    └── MuteButton_BGM
             │
             ├── SE_Section
             │    ├── Label (“SE”)
             │    ├── Slider_SE
             │    ├── Text_SE
             │    └── MuteButton_SE
             │
             └── Voice_Section
                  ├── Label (“ボイス”)
                  ├── Slider_Voice
                  ├── Text_Voice
                  └── MuteButton_Voice

音量設定の実装

AudioMixerの作成

1. 新規「Audio Mixer」を作成:名前を「SoundMixer」にする

2. 「Audio Mixer」ウィンドウ:Groupsパネルの「Master」を選択し、+ ボタンで子グループBGM」を追加

3. 「SE」「Voice」も追加:Masterの子として作ること。BGMの子にならないよう注意

4. 「Expose ‘Volume (of Master)’ to script」を選択:「Master」グループ → Inspectorの Volume 右クリック

5. 「Exposed Parametersリスト」の名前変更:「MasterVolume

6. 「BGM」「SE」「Voice」もそれぞれ同様に行う:名前は「BGMVolume」「SEVolume」「VoiceVolume

これで「BGM」「SE」「Voice」が「マスターボリューム」に連動した「Audio Mixer」の完成です。

スクリプトの作成

UI画像専用設定方法:いつものようにManagerはルート直下に。

UIオブジェクトを配置後に、対応する部分にアサインしていきます。

previewAudioSourceの設定(重要)

SE」「Voice」のプレビュー音源用に「AudioSource」を2つ作成しておきます。
今回は分かりやすいように、「SE_Audio_Source」オブジェクト「Voice_Audio_Source」オブジェクトを作り、
それぞれに「AudioSource」コンポーネントを追加しています。

BGM設定

■ AudioSource
Play On Awake:すぐに音を鳴らしたい場合はチェック。BGMはすぐに鳴らせるのでチェックしておきます。
Loop:ループさせる場合はチェック。
Priority:CPU負荷が高い瞬間に再生処理が後回しにされるのを防ぎます。0 (High)にしておきます。

Audio Clip(素材の方)
Decompress On Load:メモリ上に解凍済みの(生の)状態で保持される。
PreloadAudio Data:シーン開始時にあらかじめメモリに展開される。

低スペックPCでの「安定性」を考える

1. Load TypeDecompress On Load(解凍してロード)
理由:低スペックPCで最も怖いのは「CPUの瞬間的なスパイク(負荷の跳ね上がり)」です。
仕組み
Compressed In Memory」は再生中にリアルタイムで解凍するため、常にCPUを少しずつ使い続けます。
Decompress On Load」はメモリを多く使いますが、再生中のCPU負荷はほぼゼロになります。
判断:今回のBGMは 0.5MB と非常に軽量です。解凍しても数MB程度にしかなりません。
最近の「超ローPC」でもメモリは数GBあるはずなので、数MBのメモリを差し出してCPU負荷を減らす 方が、
動作のガタつき(スタッタリング)を防ぐ意味で圧倒的に有利です。

2. Preload Audio Datオン(チェックを入れる)
理由:「音が鳴るべき瞬間に音が鳴らない」のを防ぐためです。
仕組み
これがオフだと、再生直前にディスク(HDD/SSD)から読み込みを開始します。
低スペックPC、特にHDDを使っている環境では、この読み込み待ちで一瞬ゲームが止まることがあります。
判断:シーン開始時に読み込んでおくことで、ゲームプレイ中のディスクI/O(読み書き負荷)を減らせます。

低スペックPC向け:サウンド設計のガイドライン

種類推奨 Load TypePreload理由
BGM (短い/軽量)Decompress On LoadONCPU負荷を徹底的に排除するため。
SE (効果音全般)Decompress On LoadON反応速度(レイテンシ)が命。
鳴った瞬間の負荷をゼロにする。
Voice (長いセリフ)Compressed In MemoryOFFボイスは数が多い。
全部メモリに載せるとメモリ不足になるため。
BGM (5分以上の大曲)StreamingOFFメモリ消費を抑えるため。
ディスクから少しずつ読み込む。

BGMループで「間」が空く原因
MP3特有の無音区間(ヘッダーギャップ)
MP3という規格自体、ファイルの先頭や末尾に「数ミリ秒の無音(ヘッダー情報等)」が強制的に挿入される仕様になっています。どれだけ完璧に波形編集しても、Unityでループさせると必ず「プツッ」とした間やノイズが入ります。
解決方法:「WAV」または「OGG」形式で書き出す・変換する。

実機での挙動

今回は「AudioMixer」という音源専用機能を扱いました。
そこで若干もたつきましたが、おおむねすんなりと実装できたのではないかと思います。

音関連は奥が深そうなので、じっくりといじるターンが楽しみでもあります。

次回は、音実装の流れで提案された「SE再生マネージャー」というものを作ってみようと思います。
またManagerが増えますね…
効果音を設定する際に、ひとつひとつの作業にならないよう管理をしやすくするため、のものらしいです。
マネージャーで一元管理
これがUnityでの構築方法なのだと、やっと分かりかけてきています。

プロジェクトまとめ

システム概要

AudioMixer」を核とし「Sys_Flag_Manager(セーブデータ管理)」と連動させた、永続性のある音量管理システム。

実装済みコンポーネント

Sys_AudioSettingsManager.cs

・音量データの保持・反映・保存の司令塔。
・起動時の爆音を防ぐため、1フレーム待機してからMixerへ反映する初期化ロジックを搭載。
・スライダー値(0-100)を対数的なデシベル値(-80dB〜0dB)へ変換。

UI_AudioSettingsPanel.cs

・ユーザーインターフェースの制御。
・Masterミュート時に子要素(BGM/SE/Voice)をグレーアウトし操作不能にする排他制御。
・SEとVoiceを別々の「AudioSource」で鳴らすプレビュー機能。
・右クリックでのクイッククローズ対応。

SoundMixer (AudioMixer)

・Master / BGM / SE / Voice の階層構造。
・露出パラメータ:MasterVolume・BGMVolume・SEVolume・VoiceVolume

運用上の注意点(備忘録)

新規SE/Voiceの追加
必ず「AudioSource」の「Output」欄に「Mixer」内の適切なグループ(SEやVoice)をドラッグ&ドロップすること。
これを行わないと、設定画面で音量を下げても「爆音」で鳴り続けます。

低スペックPCへの配慮
短い音素材は「Decompress On Load(メモリ展開)」に、
長い曲やボイスは「Compressed In Memory」または「Streaming」に設定し、
CPU負荷とメモリ消費のバランスを取ること。

ロード後の挙動と修正箇所

発生していた問題

AudioSourceのMissing参照による音声停止
「Sys_Messenger」が自身にアタッチされた「AudioSource」を直接参照していたため、
セーブ&ロードやシーン遷移時にインスタンスとの紐付けが切れ、ポポポ音・ボイスが鳴らなくなる不具合が発生していた。

解決方針

「再生機」をMessengerから切り離し、常駐Managerに委譲する
Messengerは「AudioClip(音源データ)」のみを保持し、
再生処理はDontDestroyOnLoadで常駐する「Sys_AudioSettingsManager」に一元化。
Messengerがいつ生成・破棄されても再生機は常に安定して動作する。

コメント