ゲーム開発
Unity
UnrealEngine
C++
Blender
ゲーム数学
ゲームAI
グラフィックス
サウンド
アニメーション
GBDK
制作日記
IT関連
ツール開発
フロントエンド関連
サーバサイド関連
WordPress関連
ソフトウェア設計
おすすめ技術書
音楽
DTM
楽器・機材
ピアノ
ラーメン日記
四コマ漫画
その他
おすすめアイテム
おもしろコラム
  • ゲーム開発
    • Unity
    • UnrealEngine
    • C++
    • Blender
    • ゲーム数学
    • ゲームAI
    • グラフィックス
    • サウンド
    • アニメーション
    • GBDK
    • 制作日記
  • IT関連
    • ツール開発
    • フロントエンド関連
    • サーバサイド関連
    • WordPress関連
    • ソフトウェア設計
    • おすすめ技術書
  • 音楽
    • DTM
    • 楽器・機材
    • ピアノ
  • ラーメン日記
    • 四コマ漫画
      • その他
        • おすすめアイテム
        • おもしろコラム
      1. ホーム
      2. 20240122_02_unity_audio_mixer

      【Unity】第二回 UnityAudioを使いこなす 〜AudioMixer活用編〜

      UnityサウンドUnityAudio
      2024-01-22

      マイケル
      マイケル
      みなさんこんにちは! マイケルです!
      エレキベア
      エレキベア
      こんにちクマ〜〜〜
      マイケル
      マイケル
      前回に引き続き、UnityAudioによるサウンド実装を進めていきます。 今回は AudioMixer を使用して、 ・ボリューム設定画面の実装 ・サウンドエフェクトの適用 を行ってみます。
      エレキベア
      エレキベア
      Unity標準機能でもサウンドエフェクトがかけれるのクマね これは気になるクマ〜〜
      【Unity】第一回 UnityAudioを使いこなす 〜サウンド再生処理編〜
      2024-01-22
      【Unity】第二回 UnityAudioを使いこなす 〜AudioMixer活用編〜
      2024-01-22
      【Unity】第三回 UnityAudioを使いこなす 〜オーディオスペクトラム描画編〜
      2024-01-22

      参考書籍

      マイケル
      マイケル
      学習するにあたっては、下記書籍を参考にさせていただきました!

      Unityサウンド エキスパート養成講座

      マイケル
      マイケル
      Unityでのサウンド処理をまとめた数少ない書籍です! 発売日からそれなりに経過していますが、UnityAudioだけでなくCRIと連携した使い方まで解説されているため、興味を持った方はぜひ一読してみてください!
      エレキベア
      エレキベア
      サウンド専門となると書籍は中々ないクマから持っておく価値はありそうクマね

      AudioMixerの概要

      マイケル
      マイケル
      まずAudioMixerがどんなものかというと、AudioSourceが鳴らしている音を分類し調整やエフェクト処理を行う機能になります。 こちらは Window > Audio > Audio Mixer からウィンドウを開くことができ、「Mixer」欄から新規作成することができます。
      20240122_01_unity_audio_standard_12
      ▲AudioMixerの画面

      20240122_01_unity_audio_standard_17
      ▲追加したMixerはAssets配下に作成される

      エレキベア
      エレキベア
      DAWソフトとかで見るようなミキサー機能に近いクマね
      マイケル
      マイケル
      Groups欄からは Masterボリュームの子としてAudioMixerGroupを追加 することができ、例えばBGM用、SE用といった形で追加することができます。 また、各Groupには AddボタンからEffectを追加 することができ、リバーブや歪みといった一般のDAWソフトでみるようなエフェクトをかけることができます。
      20240122_01_unity_audio_standard_13
      ▲AudioMixerGroupの追加

      20240122_01_unity_audio_standard_14
      ▲エフェクトの追加

      エレキベア
      エレキベア
      うへ〜〜〜 マジでDAWソフトみたいクマ
      マイケル
      マイケル
      作成したAudioMixerGroupをAudioSourceに設定することで出力先を指定することができます。 また、Shapshotという機能もあり、編集した値をSnapshotとして保存し、指定して呼び出すこともできます。 こちらも後ほど触ってみようかと思います。
      20240122_01_unity_audio_standard_15
      ▲AudioSourceにAudioMixerGroupを紐づけることで紐づける

      20240122_01_unity_audio_standard_16
      ▲編集した値をSnapshotとして保存することができる

      エレキベア
      エレキベア
      大体使い方は分かった気がするクマ〜〜

      ボリューム調整画面の実装

      マイケル
      マイケル
      それでは早速実装していきます。 まずはAudioMixerの機能を使用して、下記のようなボリューム調整画面を作ってみます。
      20240122_01_unity_audio_mixer_02
      エレキベア
      エレキベア
      よくある設定画面クマね
      マイケル
      マイケル
      また今回作るサンプルについては下記にGitHubリポジトリとして上げています。 こちらもよければご参照ください!

      GitHub - unity-audio-sample

      エレキベア
      エレキベア
      前回と同じサンプルプロジェクトクマね

      AudioMixerGroupの作成

      マイケル
      マイケル
      まずはAudioMixerを作成し、BGM用、SE用でそれぞれAudioMixerGroupを追加します。
      20240122_01_unity_audio_mixer_03
      ▲AudioMixerGroupの追加

      マイケル
      マイケル
      そして各AudioMixerGroup内の Attenuation > Volume を右クリックして「Expose ~~」を選択します。 こうすることで、ボリューム値をスクリプト側から操作できるようになります。
      20240122_01_unity_audio_mixer_04
      ▲Volume値をExposeする

      20240122_01_unity_audio_mixer_05
      ▲3つのVolume値をExposeした状態

      エレキベア
      エレキベア
      これで準備は完了クマね

      ボリューム調整画面の実装

      マイケル
      マイケル
      次に実装の方に移っていきます。 AudioMixerのロード処理について、今回はオーディオファイルと同様にResources配下から読み込むようにしました。
              private static readonly string AudioMixerFileDirPath = "Audio/Mixer/";
      
      ・・・略・・・
      
              /// <summary>
              /// AudioMixerの読み込み
              /// </summary>
              /// <returns></returns>
              private AudioMixer LoadAudioMixer(string audioMixerName)
              {
                  return Resources.Load(AudioMixerFileDirPath + audioMixerName) as AudioMixer;
              }
      
      ▲AudioMixerの読み込み
      マイケル
      マイケル
      そしてAudioSourceとの紐付けは下記のようにしました。 用意したAudioMixerとAudioMixerGroupを名前指定で読み込み、AudioSource作成時に設定しています。
              /// <summary>
              /// AudioMixerGroup関連
              /// </summary>
              private static class AudioMixerConst
              {
                  // AudioMixer名
                  public static readonly string MainAudioMixerName = "MainAudioMixer";
      
                  // AudioMixerGroup名
                  public static readonly string MainMasterGroupName = "Master";
                  public static readonly string MainBgmGroupName = "BGM";
                  public static readonly string MainSeGroupName = "SE";
      
                  // Exposeしたパラメータ名
                  public static readonly string MasterVolumeParamName = "MasterVolume";
                  public static readonly string BgmVolumeParamName = "BGMVolume";
                  public static readonly string SeVolumeParamName = "SeVolume";
              }
      
              /// <summary>
              /// AudioMixer
              /// </summary>
              private readonly AudioMixer _mainAudioMixer;
              private readonly AudioMixerGroup _mainAudioMixerGroupMaster;
              private readonly AudioMixerGroup _mainAudioMixerGroupBgm;
              private readonly AudioMixerGroup _mainAudioMixerGroupSe;
      
      ・・・略・・・
      
              public UnityAudioService()
              {
                  // AudioMixer、AudioGroup読込
                  _mainAudioMixer = LoadAudioMixer(AudioMixerConst.MainAudioMixerName);
                  if (_mainAudioMixer != null)
                  {
                      _mainAudioMixerGroupMaster = _mainAudioMixer.FindMatchingGroups(AudioMixerConst.MainMasterGroupName)[0];
                      _mainAudioMixerGroupBgm = _mainAudioMixer.FindMatchingGroups(AudioMixerConst.MainBgmGroupName)[0];
                      _mainAudioMixerGroupSe = _mainAudioMixer.FindMatchingGroups(AudioMixerConst.MainSeGroupName)[0];
                  }
      
      ・・・略・・・
      
              }
      
              /// <summary>
              /// BGM用AudioSource生成
              /// </summary>
              /// <param name="parentObject"></param>
              /// <returns></returns>
              public AudioSource CreateBgmAudioSource(GameObject parentObject)
              {
                  return CreateAudioSource(parentObject, true, _mainAudioMixerGroupBgm);
              }
      
              /// <summary>
              /// SE用AudioSource生成
              /// </summary>
              /// <param name="parentObject"></param>
              /// <returns></returns>
              public AudioSource CreateSeAudioSource(GameObject parentObject)
              {
                  return CreateAudioSource(parentObject, false, _mainAudioMixerGroupSe);
              }
      
              /// <summary>
              /// AudioSource生成
              /// </summary>
              /// <param name="parentObject"></param>
              /// <param name="isLoop"></param>
              /// <param name="audioMixerGroup"></param>
              /// <returns></returns>
              private AudioSource CreateAudioSource(GameObject parentObject, bool isLoop, AudioMixerGroup audioMixerGroup)
              {
                  var audioSource = parentObject.AddComponent<AudioSource>();
                  audioSource.loop = isLoop;
                  audioSource.playOnAwake = false; // デフォルトでtrueのため明示的にオフにする
                  if (audioMixerGroup != null)
                  {
                      audioSource.outputAudioMixerGroup = audioMixerGroup;
                  }
                  return audioSource;
              }
      
      ▲AudioSourceとの紐付け
      マイケル
      マイケル
      そしてAudioMixerからExposeしたボリューム値を取得して公開しておきます。 この値をUIと紐づければ実装は完了です。
              /// <summary>
              /// マスターボリューム
              /// </summary>
              public float MasterVolume
              {
                  get => GetAudioMixerVolume(_mainAudioMixer, AudioMixerConst.MasterVolumeParamName);
                  set => SetAudioMixerVolume(_mainAudioMixer, AudioMixerConst.MasterVolumeParamName, value );
              }
      
              /// <summary>
              /// BGMボリューム
              /// </summary>
              public float BgmVolume
              {
                  get => GetAudioMixerVolume(_mainAudioMixer, AudioMixerConst.BgmVolumeParamName);
                  set => SetAudioMixerVolume(_mainAudioMixer, AudioMixerConst.BgmVolumeParamName, value );
              }
      
              /// <summary>
              /// SEボリューム
              /// </summary>
              public float SeVolume
              {
                  get => GetAudioMixerVolume(_mainAudioMixer, AudioMixerConst.SeVolumeParamName);
                  set => SetAudioMixerVolume(_mainAudioMixer, AudioMixerConst.SeVolumeParamName, value );
              }
      
              private static float GetAudioMixerVolume(AudioMixer audioMixer, string exposedParamName)
              {
                  audioMixer.GetFloat(exposedParamName, out var decibel);
                  if (decibel <= -96f)
                  {
                      return 0f;
                  }
                  return Mathf.Pow(10f, decibel / 20f);
              }
      
              private static void SetAudioMixerVolume(AudioMixer audioMixer, string exposedParamName, float volume)
              {
                  var decibel = 20f * Mathf.Log10(volume);
                  if (float.IsNegativeInfinity(decibel))
                  {
                      decibel = -96f;
                  }
                  audioMixer.SetFloat(exposedParamName, decibel);
              }
      
      ▲Exposeしたボリューム値の公開
      マイケル
      マイケル
      UIの実装は下記のようにしました。 Sliderとボリューム値のgetter, setterを紐づけています。
      using UnityEngine;
      using UnityEngine.Events;
      using UnityEngine.EventSystems;
      using UnityEngine.UI;
      
      namespace UI
      {
          /// <summary>
          /// オーディオ設定UI
          /// </summary>
          public class UIAudioConfig : MonoBehaviour
          {
              /// <summary>
              /// 背景タップイベント
              /// </summary>
              [SerializeField] private EventTrigger _bgImageEventTrigger;
      
              public void SetListenerBgImage(UnityAction action)
              {
                  var entry = new EventTrigger.Entry();
                  entry.eventID = EventTriggerType.PointerDown;
                  entry.callback.AddListener(call => action());
                  _bgImageEventTrigger.triggers.Add(entry);
              }
      
              /// <summary>
              /// ボリューム調整スライダー
              /// </summary>
              [SerializeField] private Slider _masterVolumeSlider;
              [SerializeField] private Slider _bgmVolumeSlider;
              [SerializeField] private Slider _seVolumeSlider;
      
              public void SetValueMasterVolumeSlider(float value)
              {
                  _masterVolumeSlider.value = value;
              }
      
              public void SetValueBgmVolumeSlider(float value)
              {
                  _bgmVolumeSlider.value = value;
              }
      
              public void SetValueSeVolumeSlider(float value)
              {
                  _seVolumeSlider.value = value;
              }
      
              public void SetListenerMasterVolumeSlider(UnityAction<float> callback)
              {
                  if (_masterVolumeSlider.onValueChanged != null)
                  {
                      _masterVolumeSlider.onValueChanged.RemoveAllListeners();
                  }
                  _masterVolumeSlider.onValueChanged.AddListener(callback);
              }
      
              public void SetListenerBgmVolumeSliderCallback(UnityAction<float> callback)
              {
                  if (_bgmVolumeSlider.onValueChanged != null)
                  {
                      _bgmVolumeSlider.onValueChanged.RemoveAllListeners();
                  }
                  _bgmVolumeSlider.onValueChanged.AddListener(callback);
              }
      
              public void SetListenerSeVolumeSliderCallback(UnityAction<float> callback)
              {
                  if (_seVolumeSlider.onValueChanged != null)
                  {
                      _seVolumeSlider.onValueChanged.RemoveAllListeners();
                  }
                  _seVolumeSlider.onValueChanged.AddListener(callback);
              }
          }
      }
      
      
      ▲ボリューム調整画面の実装
      
      ・・・略・・・
      
              /// <summary>
              /// オーディオ設定UI
              /// </summary>
              [SerializeField] private UIAudioConfig _uiAudioConfig;
      
      ・・・略・・・
      
              private void Start()
              {
      
      ・・・略・・・
      
                  _uiAudioConfig.gameObject.SetActive(false);
                  _uiAudioConfig.SetListenerBgImage(() => _uiAudioConfig.gameObject.SetActive(false));
                  _uiAudioConfig.SetValueMasterVolumeSlider(AudioService.MasterVolume);
                  _uiAudioConfig.SetValueBgmVolumeSlider(AudioService.BgmVolume);
                  _uiAudioConfig.SetValueSeVolumeSlider(AudioService.SeVolume);
                  _uiAudioConfig.SetListenerMasterVolumeSlider(value => AudioService.MasterVolume = value);
                  _uiAudioConfig.SetListenerBgmVolumeSliderCallback(value => AudioService.BgmVolume = value);
                  _uiAudioConfig.SetListenerSeVolumeSliderCallback(value => AudioService.SeVolume = value);
              }
      
      ・・・略・・・
      
      
      ▲ボリューム値との紐付け
      マイケル
      マイケル
      以上で実装は完了です。 UI側からスライダーを操作すると、AudioMixer側のボリュームも連動して変更されるのが確認できるはずです。
      20240122_01_unity_audio_mixer_06
      ▲AudioMixer側のボリュームも変更される

      エレキベア
      エレキベア
      AudioMixerと紐づけるだけで簡単に調整画面が作れたクマね

      BGM、SEへのエフェクト適用

      マイケル
      マイケル
      次に、BGMとSEに簡単なエフェクトを適用できるよう対応してみます。 今回は通常、リバーブ、歪みの3種類で切り替えれるようにしました。
      20240122_01_unity_audio_mixer_01
      ▲サンプル内のエフェクト切り替え部分

      エレキベア
      エレキベア
      なかなか面白くなってきたクマね

      エフェクト用AudioMixer作成と紐付け

      マイケル
      マイケル
      まず、エフェクトを適用するためのAudioMixerを別途作成します。 今回は ・EffectBgmAudioMixer ・EffectSeAudioMixer の2つを作成しました。
      マイケル
      マイケル
      そして作成したエフェクト用のAudioMixerをメインとなるAudioMixerにドラッグすると、下記のように出力させるAudioMixerGroupを選択するウィンドウが出てくるため、それぞれBGM、SEを選択します。
      20240122_01_unity_audio_mixer_07
      ▲エフェクト用のAudioMixerをメインとなるAudioMixerにドラッグする

      20240122_01_unity_audio_mixer_08
      ▲BGM用、SE用で紐付けが完了した状態

      エレキベア
      エレキベア
      これでエフェクト用のAudioMixerに流し込むと最終的にメインのAudioMixerにも流れていくクマね
      マイケル
      マイケル
      そしてエフェクト用のAudioMixerに ・SFX Reverb (リバーブ) ・Distortion (歪み) を追加した後、3種類のSnapshotを保存しておきます。
      20240122_01_unity_audio_mixer_09
      ▲エフェクト値を変えたSnapshotを3種類用意

      20240122_01_unity_audio_mixer_10
      ▲Snapshot: Normal (エフェクト無し)

      20240122_01_unity_audio_mixer_11
      ▲Snapshot: Reverb (残響あり)

      20240122_01_unity_audio_mixer_12
      ▲Snapshot: Distortion (歪み)

      エレキベア
      エレキベア
      なるほどクマ それぞれのSnapshotに切り替えることでエフェクト値を調整するクマね

      AudioSouceへの設定

      マイケル
      マイケル
      作成したエフェクト用のAudioMixerをAudioSourceに紐づけます。 この辺りはAudioMixer読み込み処理に追加する形で実装しました。
              /// <summary>
              /// AudioMixerGroup関連
              /// </summary>
              private static class AudioMixerConst
              {
                  // AudioMixer名
                  public static readonly string MainAudioMixerName = "MainAudioMixer";
                  public static readonly string EffectBgmAudioMixerName = "EffectBgmAudioMixer";
                  public static readonly string EffectSeAudioMixerName = "EffectSeAudioMixer";
      
                  // AudioMixerGroup名
                  public static readonly string MainMasterGroupName = "Master";
                  public static readonly string MainBgmGroupName = "BGM";
                  public static readonly string MainSeGroupName = "SE";
                  public static readonly string EffectBgmMasterGroupName = "Master";
                  public static readonly string EffectSeMasterGroupName = "Master";
      
                  // Exposeしたパラメータ名
                  public static readonly string MasterVolumeParamName = "MasterVolume";
                  public static readonly string BgmVolumeParamName = "BGMVolume";
                  public static readonly string SeVolumeParamName = "SeVolume";
              }
      
              /// <summary>
              /// AudioMixer
              /// </summary>
              private readonly AudioMixer _mainAudioMixer;
              private readonly AudioMixer _effectBgmAudioMixer;
              private readonly AudioMixer _effectSeAudioMixer;
              private readonly AudioMixerGroup _mainAudioMixerGroupMaster;
              private readonly AudioMixerGroup _mainAudioMixerGroupBgm;
              private readonly AudioMixerGroup _mainAudioMixerGroupSe;
              private readonly AudioMixerGroup _effectBgmAudioMixerGroupMaster;
              private readonly AudioMixerGroup _effectSeAudioMixerGroupMaster;
      
      ・・・略・・・
      
              public UnityAudioService()
              {
                  // AudioMixer、AudioGroup読込
                  _mainAudioMixer = LoadAudioMixer(AudioMixerConst.MainAudioMixerName);
                  if (_mainAudioMixer != null)
                  {
                      _mainAudioMixerGroupMaster = _mainAudioMixer.FindMatchingGroups(AudioMixerConst.MainMasterGroupName)[0];
                      _mainAudioMixerGroupBgm = _mainAudioMixer.FindMatchingGroups(AudioMixerConst.MainBgmGroupName)[0];
                      _mainAudioMixerGroupSe = _mainAudioMixer.FindMatchingGroups(AudioMixerConst.MainSeGroupName)[0];
      
                      _effectBgmAudioMixer = LoadAudioMixer(AudioMixerConst.EffectBgmAudioMixerName);
                      if (_effectBgmAudioMixer != null)
                      {
                          _effectBgmAudioMixerGroupMaster = _effectBgmAudioMixer.FindMatchingGroups(AudioMixerConst.EffectBgmMasterGroupName)[0];
                      }
                      _effectSeAudioMixer = LoadAudioMixer(AudioMixerConst.EffectSeAudioMixerName);
                      if (_effectSeAudioMixer != null)
                      {
                          _effectSeAudioMixerGroupMaster = _effectSeAudioMixer.FindMatchingGroups(AudioMixerConst.EffectSeMasterGroupName)[0];
                      }
                  }
      
      ・・・略・・・
      
              }
      
              /// <summary>
              /// BGM用AudioSource生成
              /// </summary>
              /// <param name="parentObject"></param>
              /// <returns></returns>
              public AudioSource CreateBgmAudioSource(GameObject parentObject)
              {
                  return CreateAudioSource(parentObject, true, _effectBgmAudioMixerGroupMaster != null ? _effectBgmAudioMixerGroupMaster : _mainAudioMixerGroupBgm);
              }
      
              /// <summary>
              /// SE用AudioSource生成
              /// </summary>
              /// <param name="parentObject"></param>
              /// <returns></returns>
              public AudioSource CreateSeAudioSource(GameObject parentObject)
              {
                  return CreateAudioSource(parentObject, false, _effectSeAudioMixerGroupMaster != null ? _effectSeAudioMixerGroupMaster : _mainAudioMixerGroupSe);
              }
      
      ▲エフェクト用のAudioMixerとAudioSourceの紐付け
      エレキベア
      エレキベア
      エフェクト用のAudioMixerがあればそちらを設定するようにしているクマね

      Snapshotの切り替え処理

      マイケル
      マイケル
      そしてSnapshotの切り替え処理は下記のように実装します。 名前と合わせてフェード時間も指定することで滑らかに切り替えることができます。
              /// <summary>
              /// BGMエフェクト変更
              /// </summary>
              /// <param name="snapshotName"></param>
              /// <param name="fadeTime"></param>
              public void ChangeBgmEffectSnapshot(string snapshotName, float fadeTime)
              {
                  if (_effectBgmAudioMixer == null)
                  {
                      return;
                  }
      
                  var snapshot = _effectBgmAudioMixer.FindSnapshot(snapshotName);
                  if (snapshot != null)
                  {
                      snapshot.TransitionTo(fadeTime);
                  }
              }
      
              /// <summary>
              /// SEエフェクト変更
              /// </summary>
              /// <param name="snapshotName"></param>
              /// <param name="fadeTime"></param>
              public void ChangeSeEffectSnapshot(string snapshotName, float fadeTime)
              {
                  if (_effectSeAudioMixer == null)
                  {
                      return;
                  }
      
                  var snapshot = _effectSeAudioMixer.FindSnapshot(snapshotName);
                  if (snapshot != null)
                  {
                      snapshot.TransitionTo(fadeTime);
                  }
              }
      
      ▲Snapshotの切り替え処理
      エレキベア
      エレキベア
      滑らかに切り替えれるのは自然でいいクマね
      マイケル
      マイケル
      以上でエフェクトが切り替えれるようになっているはずです!
      エレキベア
      エレキベア
      いい感じクマ〜〜〜

      おわりに

      マイケル
      マイケル
      というわけでAudioMixerの活用についてでした! どうだったかな??
      エレキベア
      エレキベア
      これまであまり触ってなかったクマが、想像以上に高機能で驚いたクマ スクリプトから柔軟に操作できるのも好印象クマね
      マイケル
      マイケル
      これで大体UnityAudioの活用はできるようになったけど、 次回は最後にオーディオスペクトラムを実装して終わりたいと思います! お楽しみに!!
      エレキベア
      エレキベア
      そんなことまで出来るのクマか・・・ 楽しみクマ〜〜〜〜

      【Unity】第二回 UnityAudioを使いこなす 〜AudioMixer活用編〜 〜完〜

      【Unity】第一回 UnityAudioを使いこなす 〜サウンド再生処理編〜
      2024-01-22
      【Unity】第二回 UnityAudioを使いこなす 〜AudioMixer活用編〜
      2024-01-22
      【Unity】第三回 UnityAudioを使いこなす 〜オーディオスペクトラム描画編〜
      2024-01-22

      UnityサウンドUnityAudio
      2024-01-22

      関連記事
      【Unity】Timeline × Excelでスライドショーを効率よく制作する
      2024-10-31
      【Unity】Boidsアルゴリズムを用いて魚の群集シミュレーションを実装する
      2024-05-28
      【ゲーム数学】第九回 p5.jsで学ぶゲーム数学「フーリエ解析」
      2024-05-12
      【Unity】GoでのランキングAPI実装とVPSへのデプロイ方法についてまとめる【Go言語】
      2024-04-14
      【Unity】第二回 Wwiseを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-30
      【Unity】第一回 Wwiseを使用したサウンド制御 〜基本動作編〜
      2024-03-30
      【Unity】第二回 CRI ADXを使用したサウンド制御 〜インタラクティブミュージック編〜
      2024-03-28
      【Unity】第一回 CRI ADXを使用したサウンド制御 〜基本動作、周波数解析編〜
      2024-03-28