シーンを越えるサウンド制御

サンプル内容

概要

シーンをまたいで音楽を流し続けたり、シーン切り替え時に音楽をクロスフェードで自然に切り替えたいなどといった目的で、シーンを越えてサウンド制御を行いたい場合があります。
本サンプルはシーンを越えるサウンド制御のためのスクリプトやオプション設定について説明します。

cri4u_samples_criatom_script03_main.png

操作方法

※シーン実行時は必ず「TitleScene」から開始してください。
  • 画面右上の[change scene]ボタン
    TitleSceneとGameSceneを相互に切り替えます。

シーン情報


ミドルウェア CRI ADX2 (CRI Atom)
サンプル Scriptサンプル:シーンを越えるサウンド制御
格納場所 /cri/unity/samples/UnityProject/Assets/Scenes/criatom/script/ScriptSample03_OverSceneSound/Scenes
シーンファイル ScriptSample03_TitleScene.unity
ScriptSample03_GameScene.unity
ADX2データのオリジナル データ:音楽の簡易クロスフェード


プログラムの解説

シーンを越えてサウンド制御を行うためのサンプルプロジェクトです。
手順の概要としては、最初に起動したシーンでCRI関連のオブジェクトやアプリのサウンド制御スクリプトを生成し、それをシーン終了時に破棄せずに次のシーンでも使い続けるように設定を行います。
アプリのサウンド制御はScriptSample03_SoundManagerというオブジェクトで管理して、staticな関数 ScriptSample03_SoundManager.PlayCueId() を呼び出すことでどのシーン からでもサウンド再生の呼び出しを可能にしています。
本サンプルでは各シーンの開始時にシーン専用の音楽を再生開始するようにしてあります。
サウンドデータ側で音楽の再生開始時にクロスフェードがかかる設定にしてありますので、シーンが変わっても音楽がぶつっと途切れることなく自然に切り替わります。もちろんシーンを越えてひとつの音楽を流し続けるといった実装も可能です。

シーン切り替え時にサウンド関連を破棄しないための設定

4つのオブジェクト(コンポーネント)に対して、シーン切り替え時に破棄しないための設定を行う必要があります。
(1) CriWareLibraryInitializer の"Don't Destroy On Load"チェックを「入れる」。

cri4u_samples_criatom_script03_initializer.png

(2) CriWareErrorHandler の"Don't Destroy On Load"チェックを「入れる」。

cri4u_samples_criatom_script03_error_handler.png

(3) CRIWAREオブジェクト(Cri Atom)の"Don't Destroy On Load"にチェックを「入れる」。

cri4u_samples_criatom_script03_criware.png

(4) ScriptSample03_SoundManagerスクリプトのAwake時に GameObject.DontDestroyOnLoad(this.gameObject)を実行する。
(5) ScriptSample03_SoundManagerスクリプトのAwake時に多重生成を許さないようにコードを追加する(詳細は後述)。

こうすることで、シーン切り替え時にCRI関連および ScriptSample03_SoundManager.cs が破棄されずに継続動作するようになります。
手順(5)は、最初のシーンにもう一度戻ってきた場合に ScriptSample03_SoundManager.cs が2個出来てしまわないようにするための対策です。
なお、CRIWARE Library Initializer、CRIWARE Error Handler、CRI Atom については多重生成対策済みです。

ScriptSample03_SoundManagerスクリプトの実装例

SoundManager スクリプトでは上記手順(4)(5)の実装が必要です。本サンプルを例に説明します。
手順(4)の実装は GameObject.DontDestroyOnLoad(this.gameObject) の部分です。
手順(5)の実装は isAwaked フラグに基づく GameObject.Destroy(this) の部分です。

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

public class ScriptSample03_SoundManager : MonoBehaviour {
    /* ACB file name (CueSheet name) */
    public string cueSheetName = "CueSheet_0";

    private CriAtomSource atomSourceMusic;
    static private ScriptSample03_SoundManager instance = null;

    void Awake ()
    {
        if (instance != null) {
            GameObject.Destroy(this);
            return;
        }

        /* Create the CriAtomSource for BGM. */
        atomSourceMusic = gameObject.AddComponent<CriAtomSource> ();
        atomSourceMusic.cueSheet = cueSheetName;    

        /* Do not destroy the SoundManger when scenes are switched. */
        GameObject.DontDestroyOnLoad(this.gameObject);
        instance = this;
    }

    static public void PlayCueId(int cueId){
        instance.atomSourceMusic.Play(cueId);
    }

    void OnDestroy(){
        if (instance == this) {
            instance = null;
        }
    }

}

Hierarchyに2個ずつオブジェクトが表示される症状について

本サンプルを実行すると、ScriptSample03_GameScene から ScriptSample03_TitleScene に戻った時に、Hierarchyウインドウにいくつかのオブジェクトが2つずつ表示されていることに気付くかと思います。

cri4u_samples_criatom_script03_double_object.png

これは実害ありませんので無視してください。
各オブジェクトの多重生成チェック時に、自分自身(Component)は破棄しているのですが親のゲームオブジェクト自体を破棄していないために発生している現象です。
実際、Inspectorで確認すると2個目のゲームオブジェクトの中には何もありませんし、この中身のないオブジェクトはシーンが切り替わる時に破棄されますので3つ以上にどんどん増えていくという事はありません。
中身のないオブジェクトであっても2つ表示されるのを回避するためには、多重生成判定時に親のゲームオブジェクトごと破棄する必要があります。ただしこの方法は親ゲームオブジェクトに他のコンポーネントが接続されている可能性もあり危険です。
親ゲームオブジェクト自体が常に1つしか存在しないような実装にして、それぞれのコンポーネントでは多重チェック自体が不要にするなどの対策のほうがオススメです。

任意のシーンから開始できるようにする方法について

本サンプルは、シーン破棄時や多重生成チェックに焦点をあてて説明しているため、実行開始は必ず ScriptSample03_TitleScene でなければいけないという制約がついてしまっています。
サンプル「 どのシーンからでも実行可能 」では、本サンプルを任意のシーンから実行可能にするための手順について説明してあります。

各ゲームシーンのスクリプト説明

本サンプルではサウンド再生を要求する処理自体は各シーンに固有のスクリプトから実行しています。
ScriptSample03_SoundManager.cs はシーンを越えて存在しており、さらに static な関数 SoundManager.PlayCueId() を定義してありますので、どのシーンのスクリプトからでもサウンド再生を実行することが出来ます。
本サンプルのシーン別スクリプトはとても単純で、シーン開始時に音楽の再生開始を実行しているだけです。

スクリプトファイル: Scripts/ScriptSample03_TitleScene.cs
using UnityEngine;
using System.Collections;

public class ScriptSample03_TitleScene : MonoBehaviour {

    private int     SceneMusicCueId = 1;
    private string  nextSceneName   = "ScriptSample03_GameScene";


    /* Called before the first Update(). */
    void Start () {
        /* Play BGM. */
        ScriptSample03_SoundManager.PlayCueId(SceneMusicCueId);
    }

    /* Show and control the scene-switching GUI. */
    void OnGUI(){
        if (Scene_00_SampleList.ShowList == true) {
            return;
        }

        /* Set UI skin. */
        GUI.skin = Scene_00_SampleList.uiSkin;

        Scene_00_GUI.BeginGui("01/SampleMain");
        if (Scene_00_GUI.Button(new Rect(Screen.width-250,200,150,150), "change\nscene")) {
            Application.LoadLevel(nextSceneName);               
        }
        Scene_00_GUI.EndGui();
    }   
}



CRI Middleware logo Copyright (c) 2012-2018 CRI Middleware Co., Ltd. CRI ADX2 LE マニュアル (for Unity) SDKVer.2.10版