i-school - 3Dダイビングゲーム 手順26
 以下の内容で順番に実装を進めていきます。

手順26 ーBGMの制御処理の実装ー
45.BGM用のオーディオファイルをダウンロードしてUnityにインポートする
46.スクリプトを使って、場面に合わせてBGMを自動的に切り替える制御処理を実装する(ゲーム中→クリア)



 新しい学習内容は、以下の通りです。

 ・enum のキャスト処理を利用して配列の要素番号を指定する
 ・AudioSource.Playメソッド、AudioSource.Stopメソッド、AudioSource.clip 変数



45.BGM用のオーディオファイルをダウンロードしてUnityにインポートする

1.設計


 BGMを鳴らす場面・シーンを考えて、BGMを用意します。

 まずはどの場面・シーンでBGMを鳴らすかを想定し、その種類分のBGMが必要になることを把握します。
今回は場面としては、以下の2種類です。左側が想定するファイル名、右側がBGMを鳴らす場面です。

 1.Main       --  ゲームプレイ中
 2.GameClear  --  ゲームクリア時、リザルト表示中


 BGMを鳴らす場面が固まったら、無料の音楽サイトや持っている音源などをUnityへインポートして、ゲーム内で音楽を鳴らすための準備をします。


2.BGMを再生する場面をイメージして、オーディオファイルを探してダウンロードする


 無料の音源ダウンロードサイトなどへアクセスして、頭の中で場面を思い浮かべながら、どんなBGMがよいか、視聴しながら決めていきましょう。
先ほど提示した場面に合わせて、合計で4種類のオーディオファイルを用意をしてください。

 オーディオファイルは mp3 ファイルがサイズも小さく音質もよいため、おすすめです。
そのほかのUnityで再生可能なファイルについてはこちらを確認してください。

Unity公式マニュアル
オーディオファイル
https://docs.unity3d.com/ja/2018.4/Manual/AudioFil...

 
 ダウンロードしたオーディオファイルは、上記のリストを参考にファイル名を変更しておきましょう。


3.オーディオファイルをUnityへインポートする


 Unityへオーディオファイルをインポートする方法は、画像ファイルと同じです。
Unityへドラッグアンドドロップしてフォルダへ移動することでインポートされます。

 事前に Unity内に Audio フォルダを作成しておいて、その中へインポートするようにしましょう。
今回は Audio フォルダ内に BGM フォルダと SE フォルダを作成し、BGM フォルダ内に全ファイルをインポートしています。


Audio/BGM フォルダ画像



 無料サイトからダウンロードした場合にはオーディオファイルが圧縮されている可能性がありますので、必ず解凍を行った上でUnityへインポートしてください。
解凍されていないオーディオファイルはインポートが行えません。


 以上でこの手順は完了です。


46.スクリプトを使って、場面に合わせてBGMを自動的に切り替える制御処理を実装する(ゲーム中→クリア)

1.設計


 設計としては、カメラの制御処理と同じような形になります。
キャラの着水のタイミングで、用意しておいた BGM を切り替えるメソッドを呼び出して、BGM を変更するように制御します。

 BGM 制御のタイミングは2回です。ゲーム開始時に1回、それと着水時に1回です。

 ゲーム開始時には Main 用のオーディオファイルを指定して、それを再生するようにします。

 着水(ゲームクリア)時には GameClear 用のオーディオファイルを指定して、それを再生するようにします。

 再生するためのオーディオファイルはスクリプト内に事前に登録しておいて、ゲーム内で動的に AudioClip を変更して再生するBGMを切り替えます。 
プレファブになっているゲームオブジェクトをインスタンスする場合と同じ手法です。


2.AudioManager スクリプトを作成する


 AudioSource 型の変数を宣言して、AudioSource コンポーネントを操作できるようにしておきます。
AudioSource コンポーネントを操作できれば、AudioClip 変数を参照して再生させるオーディオファイルを切り替えることが可能になります。
また、オーディオファイルの再生・停止の命令AudioSource クラスの持つメソッドで制御を行うことができます。

 合わせて、AudioClip 型の配列変数を SerializeField属性で宣言します。そうすることで配列変数の値をインスペクターからアサインすることが出来ます。
AudioClip 型にはオーディオファイルを登録することができますので、先ほど Unity にインポートしたオーディオファイルをここに事前に登録しておいて
それをゲーム内の場面に合わせて、AudioSource の AudioClip を差し替えることで、再生するオーディオファイルを変更することが出来ます。

 BGMの種類については enum の BgmType 型を作成し、事前にどのような種類があるかを登録して利用するようにします。
いまのところは Main と GameClear の2つの列挙子を作成して登録しておきます。


AudioManager.cs

 <= クリックすると開きます。



3.<enum のキャスト処理を利用して配列の要素番号を指定する>


 enum で作成した BgmType 型ですが、enum は作成すると、自動的に、登録した列挙子の順番に 0 から番号が内部情報として与えられます

  // BGMの種類を登録
  public enum BgmType {
    Main,          // 自動的に 0 が割り振られている
      GameClear      // こちらも同様に、1 が割り振られている
  }

 この番号は int 型です。そのため enum の列挙子は、登録されている名前の他に、番号の情報を利用することも出来ます

 列挙子を int 型の番号として利用するためにはキャスト処理を行います。キャストとは、型を変換する処理のことです
すべての型同士でキャストが行えるわけではなく、許可されている型の間でのみ、キャストが行えます。

 eunm の BgmType 型を int 型にする型変換の処理は許可されている処理ですので、BgmType 型を持つ列挙子を int 型に変換することが出来ます。
ここでは扱いませんが、反対に、int 型を BgmType 型にキャストして、列挙子に変換することも出来ます。

<キャスト処理>
  // 再生するBGMを設定する
  audioSource.clip = bgms[(int)bgmType];

 bgms 配列の要素番号(インデックス)の指定は int 型でしか指定できません。そのため、BgmType 型を int 型にキャストすることで
Main => 0、GameClear => 1 という形で型の変換を行って int 型にすることで、列挙子に見合った要素番号を指定することが出来ます。

 なぜこのような処理を実装しているかを補足します。

 配列は要素番号で管理を行っていますが、BGMの指定を番号にしてしまうと、BGMの数が多くなった場合に把握できず管理不全になります。
今回は2種類しかありませんが、これが20種類あった場合、bgms[11] と要素番号を指定して、その曲がどの場面の曲かを読み取るのは非常に困難になります。

 そこで、BGMの指定は BgmType 型を利用することで、どの場面の曲であるかを明示的にわかるようにしておき、
それを実際に使用する際にキャストして利用するようにしています
このようにしておけば、プログラムを読む段階で、BGM としてどんな種類が利用されているかすぐに読み取れるため、可読性の高いコードになります。

 また、BGM の指定が間違っている場合にも気づきやすくなります
例えば、ゲームオーバーの場面の曲の指定が bgms[5] ではわかりませんが、BgmType.Title と書いてあれば気づくことが出来るはずです。


4.<AudioSource.Playメソッド、AudioSource.Stopメソッド、AudioSource.clip 変数>


 AudioSource.Playメソッドを利用することで、AudioSource コンポーネントの AudioClip にアサインされているオーディオファイルをゲーム内で再生することが出来ます。

 また、AudioSource.Stopメソッドを利用することで、AudioSource コンポーネントの AudioClip にアサインされているオーディオファイルの再生を停止することが出来ます。

 再生されるオーディオファイルは、対象の AudioSource コンポーネントの AudioClip に登録されているオーディオファイルになります。
こちらはスクリプトから AudioSource.clip 変数を参照することで動的に変更することが出来ます。


ゲーム実行前



ゲーム実行時



 いずれの制御処理も、AudioSource コンポーネントを変数に代入することで命令を出すことが出来ます。

        // BGM停止
        audioSource.Stop();

        // 再生するBGMを設定する
        audioSource.clip = bgms[(int)bgmType];

        // BGM再生
        audioSource.Play();

参考サイト
Unity公式スクリプトリファレンス
AudioSource
https://docs.unity3d.com/ja/current/ScriptReferenc...
Unity公式スクリプトリファレンス
AudioSource.Play
https://docs.unity3d.com/ja/current/ScriptReferenc...
Unity公式スクリプトリファレンス
AudioSource.Stop
https://docs.unity3d.com/ja/current/ScriptReferenc...
Unity公式スクリプトリファレンス
AudioSource.clip
https://docs.unity3d.com/ja/2019.4/ScriptReference...


5.AudioManager ゲームオブジェクトを作成して AudioManager スクリプトをアタッチして設定を行う


 ヒエラルキーの空いている場所を選択して右クリックをしてメニューを開き、Create Empty を選択して空のゲームオブジェクトを1つ作成します。
名前を AudioManager に変更します。


ヒエラルキー画像



AudioManager ゲームオブジェクト インスペクター画像
 


 先ほど作成した AudioManager スクリプトをドラッグアンドドロップしてアタッチしてください。


AudioManager ゲームオブジェクト スクリプトをアタッチ後のインスペクター画像




 アタッチされた AudioManager スクリプトの設定を行います。bgms 変数は配列ですので、その長さ(配列の要素数)を設定する必要があります。
これは Size の値を変更することで指定できます。今回用意したオーディオファイルは2種類ですので、Size を 0 から 2 に変更してください。


Size を設定



 Size を 1 以上に変更すると、配列の要素を設定できる Element が追加されます。これは配列の要素番号を表しており、0 から始まります。
Element 0 は bgms[0]、Element 1 は bgms[1] を指定することで、その中身を参照できます。

 この配列は AudioClip 型ですので、Unity にインポートしたオーディオファイルを設定することが出来ます。
ドラッグアンドドロップして、Element 0 には Main 用のオーディオファイル、Element 1 には GameClear 用のオーディオファイルをアサインしてください。


<手順動画 アサイン>
https://gyazo.com/e933be6e252d19605724ce1456bd1230


AudioManager ゲームオブジェクト アサイン後のインスペクター画像




 最後に、AudioSource コンポーネントを追加します。
AudioManager ゲームオブジェクトを選択し、インスペクターの一番下にある Add Component ボタンを押して、AudioSource コンポーネントを追加します。

 AudioSource コンポーネントの設定を行います。

 Volume を 0.1 に変更してください。小さい音量から大きく調整します。

 Play on Awake のチェックを外してください

 AudioClip は None のままで問題ありません
この部分をスクリプトから操作してBGMに利用するオーディオファイルをbgms[0]、あるいは bgms[1] に設定したオーディオファイルに
ゲーム中に切り替えます。


AudioManager ゲームオブジェクト インスペクター画像



 AudioManager ゲームオブジェクトに関しての設定は完了です。


6.GameManager スクリプトを修正して、AudioManager スクリプトの PlayBGM メソッドを呼び出してBGMを変更する


 AudioManager スクリプトに用意した PlayBGM メソッドを GameManager スクリプトから呼び出すように処理を追加します。
AudioManager スクリプトを取得し、どの部分に PlayBGM メソッドを追加すればよいかを考えて実装をしてみてください。

 なお、PlayBGM メソッドの引数は BgmType 型です。
AudioManager スクリプト内で宣言されている enum ですので、指定する場合には、AudioManager.BgmType と記述してから列挙子を指定する必要があります


GameManager.cs(自分で作成しているスクリプトがある場合には、そのスクリプトを修正する)

 <= クリックすると開きます



7.ゲームを実行して動作を確認する


 PlayBGM メソッド内に Debug.Log メソッドを用意していますので、BGMが切り替わるタイミングで Console ビューに BgmType が表示されます。
ゲームの実行時に Main、着水時に GameClear と表示されれば制御成功です。
こちらを利用しつつ、BGMが指定されたタイミングで切り替わるように制御できているかを確認します。





 ボリュームを 0.1 に絞ってありますので、もしも小さいようであれば数値を大きくします。
ただしボリュームを過ぎると、SEの音が聞こえなくなる場合がありますので、その辺りを確認しながら調整を行ってください。


<実行動画 Console に切り替わるBGMが表示される>
https://gyazo.com/eaf44702317b2a3417d1d9c15a7f1b12


<実行動画 AudioClip の値がゲームの場面に応じて None => Main => GameClear と切り替わって再生されるBGMが変わる
https://gyazo.com/f2538d37e0c0509a5ef3efb4516b5dba


 以上でこの手順は終了です。

 => 次は 手順27 ーゴール地点に花輪を用意するー です。