メインコンテンツまでスキップ

オーディオシステム

OpenMonのオーディオシステムは、UnityのAudioMixer上に構築されたプールベースの2Dオーディオエンジンです。Foundation層(OpenMon.Foundation.Audio)が汎用再生エンジンを提供し、Core層(OpenMon.MCE.Audio)がゲーム固有の音量設定と永続化を追加します。

オプション画面のサウンドセクション

独立した3つのバス(全体、音楽、効果音)があり、全体バスは他の2つを置き換えるのではなく掛け合わせます。音楽をミュートしてもバトルの打撃音が消えないのはそのためです。

アーキテクチャ​

クラス層目的
AudioManagerFoundationAudioSourceプールを所有し、クリップの再生/停止/フェードを行うシングルトン
AudioLibraryFoundation各AudioClipをAudioMixerGroupにマッピングするScriptableObject
AudioReferenceFoundationクリップを名前で参照する軽量なシリアライズ可能struct
AudioSettingsManagerCore音量設定を読み書きし、ミキサーに適用する
AudioConfigurationCoreMaster、Music、FXの音量レベルを保持するシリアライズ可能データクラス
AudioInstallerFoundationIAudioManagerとIAudioLibraryをバインドするZenject ScriptableObjectInstaller
AudioSettingsInstallerCoreAudioSettingsManagerとAudioMixerをバインドするZenjectインストーラー

AudioManager​

AudioManagerはIAudioManagerを実装するシングルトン(Singleton<AudioManager>)です。自身のGameObject上で動的なAudioSourceプールを管理します。再生リクエスト時、プール内の空きソースを再利用するか、必要に応じて新しく作成します。

オーディオの再生​

// 単発再生
AudioManager.Instance.PlayAudio(myAudioReference);

// フェードイン付きループBGM
AudioManager.Instance.PlayAudio(bgmReference, loop: true, fadeTime: 1.5f);

// カスタムピッチとボリューム
AudioManager.Instance.PlayAudio(sfxReference, pitch: 1.2f, volume: 0.8f);

各呼び出しはAudioReferenceをAudioLibraryを通じて解決し、クリップとそのミキサーグループを取得して、プールされたAudioSourceに割り当てます。fadeTime > 0の場合、マネージャーは指定された時間にわたってボリュームを0から目標値まで補間するコルーチンを実行します。

オーディオの停止​

// 即時停止
AudioManager.Instance.StopAudio(bgmReference);

// 2秒かけてフェードアウト後停止
AudioManager.Instance.StopAudio(bgmReference, fadeTime: 2f);

// 緊急全停止(例:バトル中断)
AudioManager.Instance.StopAllAudios();

グローバルミュート/アンミュート​

これらのコルーチンはAudioMixerのMasterVolumeパラメータを操作し、個々のソースを停止せずにゲーム全体の出力をミュートします。シーン遷移やポーズ画面に便利です。

StartCoroutine(AudioManager.Instance.MuteAllAudios(fadeTime: 1f));
StartCoroutine(AudioManager.Instance.UnmuteAllAudios(fadeTime: 1f));

プールのライフサイクル​

プールは自己管理型です。毎フレーム、CheckAudioSourceAvailability()が全ソースをスキャンします。再生が終了したソースは利用可能としてマークされ、クリップ参照がクリアされます。他のソースがそのクリップを使用していない場合、将来のアンロードのためにFreeAudioAsset()を介してライブラリに通知されます。

AudioLibrary​

AudioLibraryは(OpenMon > Audio > Audio Libraryから作成する)ScriptableObjectで、オーディオの中央レジストリとして機能します。ゲーム内の全クリップをそのミキサーグループ(BGM、SFX、MEなど)にマッピングするSerializableDictionary<AudioClip, AudioMixerGroup>を保持します。

AudioLibrary (ScriptableObject)
+-- "battle_bgm_01" -> BGM MixerGroup
+-- "ui_confirm" -> SFX MixerGroup
+-- "level_up_jingle" -> ME MixerGroup
+-- "cry_001" -> SFX MixerGroup
...

エディット時、ライブラリはクリップ名、クリップ参照、ミキサーグループのフラットリストをキャッシュし、名前によるO(n)の高速検索を実現します。コンテキストメニューのCache Audio Referencesコマンドで、クリップの追加・削除後にこれらのキャッシュを再構築できます。

エディターユーティリティ​

インポーターパイプラインはクリップを自動登録できます:

audioLibrary.AddAudioIfItsNotIn(clip, mixerGroup);

AudioReference​

AudioReferenceは単一のstring Audioフィールドを持つシリアライズ可能なstructです。AudioLibraryに登録されたクリップ名と一致します。これにより、シーン/プレハブのシリアライズデータとクリップへの直接参照が分離され、インスペクター参照を壊さずにオーディオファイルを再編成できます。

[Serializable]
public struct AudioReference
{
public string Audio; // AudioLibrary内の名前と一致する必要があります
}

MonoBehaviour、ScriptableObject、CommandGraphノードでAudioReferenceフィールドを使用して、名前でオーディオを参照します。

AudioSettingsManager​

AudioSettingsManagerはゲーム固有の音量コントローラーです。永続設定システムからAudioConfigurationを読み取り、3つのレベルをAudioMixerに適用します:

  • MasterVolume — ゲーム全体の音量
  • MusicVolume — BGMミキサーグループの音量
  • FXVolume — 効果音とジングルの音量

音量変換​

人間の音量知覚は対数的です。システムはAudioUtilsを使用して、スライダーの線形0-1範囲とUnityのAudioMixerが必要とするデシベルスケールを変換します:

float db = AudioUtils.LinearVolumeToLogarithmicVolume(0.5f); // ~ -6 dB
float linear = AudioUtils.LogarithmicVolumeToLinearVolume(-6f); // ~ 0.5

設定の永続化​

音量設定はIConfigurationManagerシステムを介して保存されます。プレイヤーがオプション画面でスライダーを調整すると、UIが以下を呼び出します:

audioSettingsManager.SetAudioConfiguration(new AudioConfiguration
{
MasterVolume = masterSlider.value,
MusicVolume = musicSlider.value,
FXVolume = fxSlider.value
});

これにより設定がディスクに書き込まれ、新しい値が即座にミキサーに適用されます。起動時、AudioSettingsManager.Construct()がZenjectインジェクションを介して呼び出され、保存された設定が次のフレームで適用されます。

依存性注入のセットアップ​

両方のインストーラーはシーンのSceneContextに追加されるZenject ScriptableObjectInstallerです:

  1. AudioInstaller — IAudioManager(AudioManager.Instance経由)、IAudioLibrary(AudioLibraryアセット経由)、AudioMixerをバインド。
  2. AudioSettingsInstaller — AudioSettingsManagerをレイジーシングルトンとしてバインドし、AudioMixerを注入。
SceneContext
+-- AudioInstaller (AudioLibraryアセット + AudioMixerを参照)
+-- AudioSettingsInstaller (AudioMixerを参照)

CommandGraphでの使用​

NPCイベントスクリプト(CommandGraph)からオーディオ再生をトリガーできます。Sounds カテゴリにノードがあります:PlayMusic(マップ自身の音楽の上に、ワールドの音楽としてトラックを流す)、StopMusic(フェードアウトさせる)、SaveMusic と RestoreSceneMusic(バトルの後もトラックを保持する、またはマップ自身の音楽へ戻る)、PlaySound、PlayMonsterCry、WaitForAudio(ジングルが終わるまでグラフを待機させる)。これらのノードはAudioReferenceフィールドを介してクリップを参照し、ランタイムで同じAudioLibraryを通じて解決されます。プロジェクトにすでにあるクリップでライブラリを埋めるには、Tools > MCE > Audio > Populate Audio Library を使います。

まとめ​

目的使用するAPI
効果音を再生AudioManager.Instance.PlayAudio(ref)
BGMをループ再生AudioManager.Instance.PlayAudio(ref, loop: true)
新しいBGMにクロスフェード古いBGMをfadeTimeで停止、新しいBGMをfadeTimeで再生
シーンロード中にミュートMuteAllAudios(fadeTime) / UnmuteAllAudios(fadeTime)
新しいクリップを登録AudioLibraryアセットに追加し、ミキサーグループを割り当て
プレイヤー音量を調整AudioSettingsManager.SetAudioConfiguration(config)
スライダー値をdBに変換AudioUtils.LinearVolumeToLogarithmicVolume(value)