i-school - BGMを鳴らす
 こちらの記事の拡張版です。
@nmxi様
今日からはじめるUnity
https://qiita.com/nmxi/items/7950fb12ef925efa276d



 シーンの開始と同時にBGMを鳴らす方法です。いくつか方法がありますが、ここでは一番簡単な方法をご紹介します。

 まずは設計と実装手順についてまとめておきます。

1.再生したいBGMを管理するためのオブジェクトを作成します
2.アセットストアあるいは検索エンジンを利用して、無料の音楽素材を入手します
3.インポートする音源ファイルを1つのフォルダにまとめられるようにBGMフォルダを作成します
4.音源ファイルをUnityにインポート(追加)します
5.音源ファイルをUnityで再生するようにAudioSourceコンポーネントを追加します
6.AudioSource内のAudioClipの「None」の場所に、鳴らしたい音源ファイルをアサイン(指定)します
7.エディターにてゲームを実行すると、BGMが再生されるようになります。

1.再生したいBGMを管理するためのオブジェクトを作成します


 ヒエラルキーのcreateボタンを押して、CreateEmptyを選択します。
 空のGameObject(ゲームオブジェクト)が作成されますので、名前を「Audio」や「BGM」などわかりやすい名称に変更します。


2.アセットストアあるいは検索エンジンを利用して、無料の音楽素材を入手します


 「BGM ゲーム 無料」などを打つと検索が可能です。
 ダウンロードしてPCに保存してください。音源ファイルはサイズの小さい、mp3ファイルがおすすめです。

3.インポートする音源ファイルを1つのフォルダにまとめられるようにBGMフォルダをします


 Assetsフォルダ内でマウスの右クリックをして create -> forder を選択し、新規フォルダを作成します。
 名前を「BGM」にしてください。ここに音源ファイルをインポートするようにして、ファイルを1か所にまとめて整理できるようにしておきます。


4.音源ファイルをUnityにインポート(追加)します


 インポートしたい音源ファイルを選んでUnityの Assets / BGM フォルダ内にドラッグ&ドロップします。
 BGMフォルダ内を確認してみてください。音源ファイルが追加されていれば成功です。これでUnityに音源ファイルがインポートされます。


5.音源ファイルをUnityで再生するようにAudioSourceコンポーネントを追加します


 先ほどヒエラルキーに作成した「Audio(BGM)」オブジェクトを選択して、右側のインスペクターを確認してください。
現在はTransformコンポーネントのみアタッチされている状態ですので、インスペクターの最下段より「Add Component」を選択します。
 
 Audio -> AudioSource を選択するとAudio(BGM)ゲームオブジェクトに AudioSource コンポーネントが追加されます。


6.AudioSource内のAudioClipの「None」の場所に、鳴らしたい音源ファイルをアサイン(指定)します


 先程作成したBGMフォルダより、ゲーム内で再生したい音源ファイルを1つ選んで、
Audio(BGM)ゲームオブジェクトのAudioClip 欄にドラッグ&ドロップしてアサインします。(下記の動画を参照してください)

 AudioSource コンポーネントの Loop(音源の再生が終了した場合、最初からもう一度ループ再生させる)と PlayOnAwake(ゲーム開始と同時に再生)には、チェックを入れたままで大丈夫です。

https://gyazo.com/5b52ba29b9635d4c4513d087de22865c

7.エディターにてゲームを実行すると、BGMが再生されるようになります


 もしも再生されない場合にはGameビューの Mute Audio のチェックがオンに入っていないか確認してみてください。(オンだと鳴りません。画像の状態がスイッチオフです。)


 この設定を各シーンにおいて行うことで、すべてのシーンでBGMを鳴らすことが出来るようになります。

<応用> Mainシーンのゲーム状態の内容に応じてResultシーンで再生するBGMを変化させる


 Resultシーンにはゲームの状態に応じて、クリアしている場合と、ゲームオーバーになっている場合の2種類の状態があります。
現在の方法ではどちらの状態でResultシーンに遷移しても同じBGMが鳴るため、応用として、このゲームの状態に応じて、BGMを変化させるようにします。

 設計としましては、AudioSourceコンポーネントのAudioClipプロパティの情報を、ゲームの状態に合わせてスクリプトから変更します。
AudioSourceコンポーネントがCDプレイヤーの役割で、AudioClip欄は再生したいCDが入る場所、だと考えて頂くとイメージがわきやすいと思います。

 この応用では「スクリプトの処理によってゲーム内で動的に再生する音源ファイルを変更する」処理について学習し、
ゲームクリア時のBGMと、ゲームオーバー時のBGMとで、別々のBGMを鳴らすようにしましょう。

 設計と実装手順についてまとめておきます。

1.最初の「BGMを鳴らす」の手順1〜5までを行って、ResultシーンにAudioゲームオブジェクトを作成し、AudioSourceコンポーネントを追加する所まで同じ状態で進めます
2.DataSenderスクリプトを修正してMainシーン終了時にゲームの状態を保持できるようにします
3.TextDataFetcherスクリプトを修正し、ゲームの状態に応じて音源を変更して再生できるようにします
4.GameMasterスクリプトとKabeOutスクリプトにあるGameOver関数を呼び出す処理をそれぞれ修正して、isGameClear変数に値を代入する処理を追加します
5.ゲームを実行してゲームクリア時とゲームオーバー時のBGMが変化するか確認します

1.最初の「BGMを鳴らす」の手順1〜5までを行って、ResultシーンにAudioゲームオブジェクトを作成し、AudioSourceコンポーネントを追加する所まで同じ状態で進めます


 6以降の手順は行わないでください。(AudioSourceコンポーネントのAudioClip欄はNoneのままにしておいてください。)



2.DataSenderスクリプトを修正してMainシーン終了時にゲームの状態を保持できるようにします


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class DataSender 
{
    public static string resultMessage;
    public static bool isGameClear;           // <= 追加
}

 bool型のisGameClear変数を新しくstaticの情報として追加しました。この変数がゲームの状態を表現します。
この変数を使ってMainシーンを終了するタイミング(GameOver関数を呼び出す処理)で true / false を切り替えるようにします。
isGameClear == true であれば「ゲームクリアの状態」
isGameClear == false であれば「ゲームオーバーの状態」

とすることで、この情報を使い、制御文を使ってMainシーンの結果によってResultシーンの再生する音源を分岐させることが可能になります。

3.TextDataFetcherスクリプトを修正し、ゲームの状態に応じて音源を変更して再生できるようにします

 
新しく変数を2つ宣言します。また、Startメソッド内に分岐処理を追加して、ゲームの状態に応じて音源を変更して再生できるようにします

TextDataFetcher.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; //これがあることで、UnityEngine.UI.Textと書かなくてもよくなる

public class TextDataFetcher : MonoBehaviour
{
    // Textクラス型の参照型変数resultMessageTextには、このスクリプトが適用されているオブジェクト(=Masterオブジェクト)のInspecterタブのResultMessageTextに指定したオブジェクト(=結果を入れる方のTextゲームオブジェクト)のID番号が格納される。
    public Text resultMessageText;

    // AudioClipクラス型の配列audioClipsの要素には、このスクリプトを適用したMasterオブジェクトのInspectorタブのAudio ClipsのElement0、Element1に指定した音楽のID番号が格納される
    public AudioClip[] audioClips;    // <= ☆ 追加

    // AudioSourceクラス型の参照型変数audioSourceには、このスクリプトを適用したMasterゲームオブジェクトのInspectorタブのAudio Sourceに指定したAudioオブジェクトのID番号が格納される
    public AudioSource audioSource;   // <= ☆ 追加

    void Start()
    {
        // resultMessageTextに格納されているID番号が指すオブジェクト(=結果を入れる方のTextゲームオブジェクト)の参照型変数textに
        // DataSenderクラスの参照型変数resultmessageに格納されているID番号が指すオブジェクト(=新しい文字列が記載されているオブジェクト)のID番号を代入する。
        // これによって、結果を入れる方のTextゲームオブジェクトの文字列が新しい文字列に入れ替わる。
        resultMessageText.text = DataSender.resultMessage; 

///* 以下の処理を追加します *///

    // 音源の変更分岐処理。ここでゲームの状態に応じて再生する音源ファイルを決定してAudioSourceのAudioClipにセットする
        // もしDataSenderクラスの変数isGameClearがtrueなら、ゲームクリアの状態とする
        if (DataSender.isGameClear)
        {
            // (配列audioClipsの先頭アドレス+0番目のアドレスの中身である)Element0のID番号を参照型変数clipに格納する 
            audioSource.clip = audioClips[0]; 
        }
        // もしDataSenderクラスの変数isGameClearがfalseなら、ゲームオーバーの状態とする
        else
        {
            // (配列audioClipsの先頭アドレス+1番目のアドレスの中身である)Element1のID番号を参照型変数clipに格納する 
            audioSource.clip = audioClips[1]; 
        }
  
        // 参照型変数clipに格納されているID番号が指し示す音楽を再生する
        audioSource.Play();
    }

///* ここまで *///

}

 Startメソッド内にisGameClearの状態を確認する分岐処理を作って、ゲームの状態に応じて再生する音源を設定するようにします。
この処理によってゲームクリア時とゲームオーバー時の音楽が変化するようになります。

 スクリプトの修正が終わったら、Masterゲームオブジェクトのインスペクターを確認してください。public修飾子で宣言した変数が2つ追加されています。


 AudioClipsには、Resultシーンで再生する音源ファイルを指定します。こちらは配列ですので、Sizeを2に変更するとElement情報0 -1が追加されますので
どちらもBGMフォルダから、Element0にはゲームクリア時の音源ファイルをアサインします。Element1にはゲームオーバー時の音源ファイルをアサインします。


 AudioSourceには、ヒエラルキーにあるAudioゲームオブジェクトの持つAudioSourceコンポーネントをアサインします。
ヒエラルキーにあるAudioゲームオブジェクトをドラッグアンドドロップして、こちらにアサインします。

アサイン動画
https://gyazo.com/13d1ea68f5141c9fee7575fac29834f8 

完成状態のインスペクター画像


4.GameMasterスクリプトとKabeOutスクリプトにあるGameOver関数を呼び出す処理をそれぞれ修正して、isGameClear変数に値を代入する処理を追加します


GameMaster.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; //SceneManager.LoadScene("Result");を動かすために必要

public class GameMaster : MonoBehaviour
{
  (省略)

    void Update()
    {
        // nowTimeに今までに経過した時間を入れています.Time.deltaTimeでは前のフレームから経過した時間を取得できます.
        // Update()は毎フレーム実行されるのでその経過時間を毎フレーム足すことで経過時間を取得することができます
        nowTime += Time.deltaTime;
        
        // もし今のボックス数が0以下ならGameOver関数を呼び出し、Resultシーンに移動する。
        if (boxNum <= 0)
        {
            // nowTime.ToString("F0")=nowTimeを小数点第0位まで(=小数点以下なし)の文字列に変換する
            GameOver(nowTime.ToString("F0")+"秒でクリアできた!", true);        // <= ☆ 第2引数として true を追加し、ゲームクリアの状態を渡す
        }
    }

    /// <summary>
    /// ゲーム終了時によばれる処理
    /// ゲーム終了とは、ゲームクリア時とゲームオーバー時の2種類がある
    /// </summary>
    /// <param name="resultMessage">ゲームの状態に合わせたメッセージが代入されている</param>
    /// <param name="isGameClear">Mainシーン終了時のゲームの状態が代入されている。true = ゲームクリア、false = ゲームオーバー</param>
    public void GameOver(string resultMessage, bool isClear)                   // <= ☆ 第2引数を追加。ゲームの状態を受け取るようにする
    {
        DataSender.resultMessage = resultMessage;

        // ゲームの状態(ゲームクリアならtrue、ゲームオーバーならfalseとして値が引数に届いている)を代入
        DataSender.isGameClear = isClear;                                      // <= ☆ 追加。第2引数の情報をstaticの変数に代入する。この情報はシーン遷移しても失われない

        // Resultという名前の”シーン”に移動しろ.という命令
        SceneManager.LoadScene("Result");
    }
}



KabeOut.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class KabeOut : MonoBehaviour
{
    // このスクリプトが適用されているゲームオブジェクトにオブジェクトがあたってきたとき、この関数は呼ばれる。
    // あたってきたオブジェクトのID番号が引数として、参照型変数collisionに代入される。
    private void OnCollisionEnter(Collision collision)
    {
        //Masterオブジェクトの持つGameMasterコンポーネント(スクリプト)のGameOver関数を呼ぶ
        GameObject.Find("Master").GetComponent<GameMaster>().GameOver("ゲーム失敗. また挑戦しよう", false);   // ☆ <= 第2引数を追加する
    }
}

 各スクリプトにあるGameOver関数を呼び出す処理に、第2引数(bool型の情報)を追加します。この値をisGameOver変数に代入することで、Resultシーンで音源の分岐処理が行えるようになります。

5.ゲームを実行してゲームクリア時とゲームオーバー時のBGMが変化するか確認します


 ゲームを実行して動作の検証を行いましょう。ゲームクリア時とゲームオーバー時のBGMが変化していれば成功です。
その場合ResultシーンのヒエラルキーのAudioゲームオブジェクトのAudioSourceコンポーネントをインスペクターで確認してみましょう。
NoneであったAudioClip欄に、自動的に再生する音源ファイルがアサインされているはずです。(この例では、ゲームクリア時にはBGM3、ゲームオーバー時にはBGM4がアサインされます)


実行前のAudioClip(None)


ゲームクリア時のAudioClip


ゲームオーバー時のAudioClip



 処理がうまくいかない場合にはDebug.LogでisGameClearの値がどのようになっているか、isGameClearの値を使った分岐処理に書き間違いはないかを確認してみましょう。