(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!


誰でも簡単に使える最強のAudio(BGM, SE)Manager【Unity】


このエントリーをはてなブックマークに追加


この記事はUnity Advent Calendar 2019の12日目の記事です。


この記事でのバージョン
Unity 2017.4.17f1
Unity 2018.4.13f1
Unity 2019.2.15f1


はじめに

以前、AudioManagerの記事を公開したのですが、

Unityは音を鳴らすのがちょっと面倒なせいか、いまだに結構多くの方に使ってもらえているらしいです。




公開から年数も経ってますし、いつかプログラムも記事も書き直したいな〜と思っていたのですが、

どう考えても時間がめっちゃかかるので後回しにしてたら、5年も経ってしまっていました。


という事で今回は、Advent Calendarに乗じてAudioManagerを一新しようという感じの記事です!

なお、「初心者の方でも簡単に使える」というのを目標に作っています。


AudioManagerとは

そもそもAudioManagerとはなんぞやという話からですが、

読んで字の如く、BGMやSEなどのオーディオファイルの再生や停止を管理する物です。


Unityは音を鳴らすだけでもAudioSouce、AudioListener、AudioClipなど様々な要素が関わってくるので、

色々準備や設定が面倒ですし、初心者が混乱するポイントだったりもします。


そこで、とにかく簡単に音を鳴らすためにAudioManagerを作りました!


導入

今回のAudioManagerはGitHubに公開してみました。もちろん完全無料で使えます!



GitHubがよう分からんという方は、Download ZIPからzipファイルをダウンロードするだけでOK。

f:id:kan_kikuchi:20191212151143j:plain


後はUnityPackageを自分のプロジェクトへインポートするだけ。

f:id:kan_kikuchi:20191212151422j:plain
f:id:kan_kikuchi:20191212151457j:plain


ちなみにインポートされたAudioManager_KanKikuchiという

ディレクトリは移動しても名前を変えてもOKです。

f:id:kan_kikuchi:20191212151559j:plain



使い方

AudioManagerを導入すると、

どのシーンを再生してもBGMManagerとSEManagerのオブジェクトが自動生成されるようになり、

いつでもどこでもBGMやSEを簡単に再生出来るようになります。

f:id:kan_kikuchi:20191212152330j:plain


例えばプログラムからSEを再生したい場合は1行追加するだけです。

//System20というSEを再生
SEManager.Instance.Play(SEPath.SYSTEM20);


ただし、シーン上にAudioListenerが最低1つは必要です。

(デフォルトのカメラに付いているので、特に設定は不要なはずです。)

f:id:kan_kikuchi:20191212153846j:plain


なお、基本的な動作はBasicSampleSceneを見ると分かりやすいかと思います。

f:id:kan_kikuchi:20191212152037j:plain



オーディオファイル(AudioClip)の場所

オーディオファイル(AudioClip)はAudioManager_KanKikuchi/Resourcesの下に配置します。

なお、BGMとSEはディレクトリを分けてありますが、

BattleやJingleのようにそれより下にディレクトリを追加する事は可能です。

f:id:kan_kikuchi:20191212153124j:plain


また、デフォルトで配置されているファイルを削除したり、新たに追加する事も、もちろん可能です。

ただし、サンプルでエラーが出るので、その場合はサンプルをディレクトリごと消してください。


オーディオファイルを追加したり名前を変えたりすると、

パスを管理するクラス(BGMPathとSEPath)が自動で更新され、

ディレクトリごとにAudioClipの設定も自動で更新されます。


プログラム

ここでは実際にプログラムでどう使うかの紹介です。

なお、AudioManager関連の機能を使うにはusing KanKikuchi.AudioManager;の記述が必要になります。


再生

BGMの再生にはBGMManagerを使います。

以下のようにInstanceにアクセスして使う感じなので、どこからでも再生可能です!

BGMManager.Instance.Play(BGMPath.BATTLE27);


なお、再生時に色々と設定する事も可能です。(audioPath以外は全て省略可能)

BGMManager.Instance.Play(
  audioPath       : BGMPath.BATTLE27, //再生したいオーディオのパス
  volumeRate      : 1,                //音量の倍率
  delay           : 0,                //再生されるまでの遅延時間
  pitch           : 1,                //ピッチ
  isLoop          : true,             //ループ再生するか
  allowsDuplicate : false             //他のBGMと重複して再生させるか
);


SEの再生にはSEManagerをBGMと同じような感じで使います。

SEManager.Instance.Play(SEPath.SYSTEM20);


ただし、BGMとは違い引数でcallbackが指定出来ます。(SEの重複再生は常に可能)

SEManager.Instance.Play(
  audioPath       : SEPath.SYSTEM20, //再生したいオーディオのパス
  volumeRate      : 1,                //音量の倍率
  delay           : 0,                //再生されるまでの遅延時間
  pitch           : 1,                //ピッチ
  isLoop          : true,             //ループ再生するか
  callback        : null              //再生終了後の処理
);


ちなみに、前述の通りBGMPathやSEPathは自動更新されるので、

使いたいオーディオファイルを入れるだけで、プログラムからもすぐに使えます。


ボリュームの変更

音源ごとのボリュームはPlayのvolumeRateで指定しますが、

全体のボリュームを変更したい時にはChangeBaseVolumeを使います。

/*volumeはfloat*/
//BGM全体のボリュームを変更
BGMManager.Instance.ChangeBaseVolume(volume);

//SE全体のボリュームを変更
SEManager.Instance.ChangeBaseVolume(volume);


なお、再生中の音のボリュームも変更されます。

停止

再生しているものを停止させたい時はStopを使います。

//全てのBGMを停止
BGMManager.Instance.Stop();

//全てのSEを停止
SEManager.Instance.Stop();


なお、指定した音源だけを停止する事も可能です。

//BATTLE27のBGMだけを停止
BGMManager.Instance.Stop(BGMPath.BATTLE27);

//SYSTEM20のSEだけを停止
SEManager.Instance.Stop(SEPath.SYSTEM20);



一時停止と再開

一時停止させたい時はPause、再開させたい場合はUnPauseを使います。

//全てのBGMを一時停止
BGMManager.Instance.Pause();

//全てのSEを一時停止
SEManager.Instance.Pause();
//一時停止している全てのBGMを再開
BGMManager.Instance.UnPause();

//一時停止している全てのSEを再開
SEManager.Instance.UnPause();


なお、指定した音源だけを一時停止及び再開する事も可能です。

//BATTLE27のBGMだけを一時停止
BGMManager.Instance.Pause(BGMPath.BATTLE27);

//SYSTEM20のSEだけを一時停止
SEManager.Instance.Pause(SEPath.SYSTEM20);
//一時停止しているBATTLE27のBGMだけを再開
BGMManager.Instance.UnPause(BGMPath.BATTLE27);

//一時停止しているSYSTEM20のSEだけを再開
SEManager.Instance.UnPause(SEPath.SYSTEM20);



フェードイン、フェードアウト

フェードインさせたい時はFadeIn、フェードアウトさせたい場合はFadeOutを使います。

また、Fadeを使えばで指定の範囲でフェードさせる事も可能です。

//全てのBGMをフェードアウト
BGMManager.Instance.FadeOut();

//全てのSEをフェードイン
SEManager.Instance.FadeIn();


もちろん、引数でフェードする時間やフェード後の処理を指定する事も出来ますですし、

指定した音源だけをフェードする事も可能です。

//再生しているBATTLE27だけ2秒でーフェードアウトし、フェードアウト後にログを表示
BGMManager.Instance.FadeOut(BGMPath.BATTLE27, 2, () => {
  Debug.Log("BGMフェードアウト終了");
});



再生中のものを取得

IsPlayingで現在再生しているか

GetCurrentAudioNamesで現在再生しているオーディオ名を取得する事が出来ます。

if (BGMManager.Instance.IsPlaying()) {
  /*BGMが再生している時の処理*/
}
//再生中のSEの名前を全て取得
var currentSENames = SEManager.Instance.GetCurrentAudioNames();



Manager以外の便利なクラス

Manager以外にも、便利なクラスをいくつか用意したので、それについても紹介しておきます。


SEAssistant

SEAssistantをSEをさらに簡単に再生するためのクラスです。

オブジェクトにAddし、鳴らしたいAudioClipを設定した後、

ボタンなどに登録すると、プログラム無しでSEを再生できます。

(もちろんSEAssistantをプログラムから使う事も可能)

f:id:kan_kikuchi:20191212171945j:plain


なお、Inspectorの各設定項目の内容は以下の通りです。

  • Audio Clip : 再生する対象
  • Is Auto Play : 自動で再生を開始するか
  • VolumeRate : ボリュームの倍率
  • Delay : 再生開始前の遅延時間
  • Pitch : 再生時のピッチ
  • Fade In Duration 再生開始時のフェードイン時間(0ならフェードインしない)
  • Is Loop : ループ再生するか


ちなみにAssistantSampleのボタンで使用例を確認出来ます。

(ただし、AssistantSample1とAssistantSample2をビルドターゲットに設定する必要が有り)


BGMAssistant

BGMAssistantをBGMをさらに簡単に再生するためのクラスです。

SEAssistant同様にプログラム無しでBGMを再生でき、

シーンごとに自動でBGMを変更するなんて事も可能です。

(もちろんBGMAssistantをプログラムから使う事も可能)

f:id:kan_kikuchi:20191212172545j:plain


なお、Inspectorの各設定項目の内容は以下の通りです。

  • Audio Clip : 再生する対象
  • Is Auto Play : 自動で再生を開始するか
  • VolumeRate : ボリュームの倍率
  • Delay : 再生開始前の遅延時間
  • Pitch : 再生時のピッチ
  • Fade In Duration 再生開始時のフェードイン時間(0ならフェードインしない)
  • Fade Out Duration 再生終了時のフェードアウト時間(0ならフェードアウトしない)
  • Is Loop : ループ再生するか
  • Is Auto Stop : シーン遷移時に自動で停止するか


これもAssistantSampleで使用例を確認できます。


BGMSwitcher

BGMSwitcherはBGMの切り替えを簡単に行うためのクラスで、

以下のように現在再生中のBGMを1行で好きなように切り替えられます。

(PlayやFade等と同様に省略可能な引数が多数あります)

//再生中のものをフェードアウトさせて、BATTLE27を再生開始する
BGMSwitcher.FadeOut(BGMPath.BATTLE27);

//再生中のものを即停止させて、BATTLE27をフェードインで開始する
BGMSwitcher.FadeIn(BGMPath.BATTLE27);

//再生中のものをフェードアウトさせて、BATTLE27をフェードインで開始する
BGMSwitcher.FadeOutAndFadeIn(BGMPath.BATTLE27);

//再生中のものをフェードアウトさせて、同時にBATTLE27をフェードインで開始する
BGMSwitcher.CrossFade(BGMPath.BATTLE27);


なお、実際の動作はBGMSwitchSampleで確認できます。


機能と設定

パスの自動更新など、特殊な機能がいくつか登場しましたが、最後にその機能をまとめておきます。


またそれらの設定はResourcesの下にあるAudioManagerSetting

Inspectorから変更する事が出来ます。(基本的にはデフォルト設定で問題はないはず)

f:id:kan_kikuchi:20191212173818j:plain



Resourcesへのパスの自動更新

ResourcesへのパスをまとめたクラスであるBGMPathとSEPathは自動で更新されます。

ただし、対象はAudioManager_KanKikuchi/Resources/BGMやSE以下のAudioClipだけです。

(AudioManager_KanKikuchiのディレクトリ名は変更可能)

f:id:kan_kikuchi:20191212175115j:plain


なお、設定から自動更新をなくす事も可能です。

f:id:kan_kikuchi:20191212175438j:plain


また、上部メニューから手動で更新する事も可能です。

f:id:kan_kikuchi:20191212175545j:plain



同時再生(可能数)

BGMもSEも同時に複数のものを再生する事が可能ですが、その再生可能数を設定出来ます。

f:id:kan_kikuchi:20191212175746j:plain


なお、再生可能数を超えた場合、一番古い音源の再生が強制的にストップします。


ボリューム設定

各音源ではなく全体のボリュームを設定する事も出来ます。

f:id:kan_kikuchi:20191212175806j:plain



SEのボリューム倍率調整

同時に同じSEを流すと爆発的にボリュームが上がり、音割れを引き起こす事がありますが、

それが起こらないように自動で調整するように実装してあります。


ただし、その調整が必要ない場合は設定から無くすことも出来ます。

f:id:kan_kikuchi:20191212175926j:plain



Managerの自動生成と破棄

Managerはシーン再生時に自動で生成され、永久に破棄されませんが、

設定から自動で生成しない事も可能ですし、

f:id:kan_kikuchi:20191212180431j:plain


シーンを跨ぐ時に破棄する設定にする事も可能です。

f:id:kan_kikuchi:20191212180438j:plain


なお、同然ですがManagerがないと機能は使えないので、

自動生成しない場合は以下のような感じで手動で生成する必要があります。


//AudioManagerの生成
gameObject.AddComponent<BGMManager>();
gameObject.AddComponent<SEManager>();



キャッシュ

AudioClipは何度もロードしないようにキャッシュしていますが、その設定も変える事が出来ます。

f:id:kan_kikuchi:20191212180547j:plain



オーディオファイルの設定の自動更新

AudioManager_KanKikuchi/Resources/BGMやSE以下の

AudioClipの設定は自動で行うようになっていますが、その自動の設定をなくしたり

f:id:kan_kikuchi:20191212180813j:plain


自動の設定の内容を変える事も出来ます。

f:id:kan_kikuchi:20191212180822j:plain


また設定ファイルのボタンやメニューから手動で設定を更新する事も可能です。

f:id:kan_kikuchi:20191212180903j:plain
f:id:kan_kikuchi:20191212180907j:plain



おわりに

5年ぶりに1から作り直しましたが、予想通りめちゃめちゃ時間かかりました……!

そのおかげで手前味噌ながら、結構良いものが出来た気がしますのでドンドン使ってみてください!


ただし実際に運用したわけでないので、バグ等があるかもしれないという事だけご注意ください。

なお、その際は報告を頂けると幸いです。(すぐに直せるとは限りませんが……)