CRIWARE Unity Plugin Manual  Last Updated: 2024-07-12
跨场景的声音控制

范例描述

概述

或许你想要跨场景地控制声音,例如播放音乐,又或者在等级变化时将音乐淡出淡入。
该范例描述了用于跨场景地控制声音的脚本和设置。

cri4u_samples_criatom_script03_main.png

操作

请确保从"TitleScene(开始页面)"开始。
  • 屏幕右上角的change scene按钮
    在TitleScene以及GameScene中切换。

场景信息


中间件 CRI ADX (CRI Atom)
范例 Script sample: Sound control across scenes(脚本范例:跨场景的声音控制)
存储路径 /CRIWARE/SDK/unity/samples/UnityProject/Assets/Scenes/criatom/script/ScriptSample03_OverSceneSound
场景文件 ScriptSample03_TitleScene.unity
ScriptSample03_GameScene.unity
原始ADX数据 数据:简易的音乐交叉淡入淡出


程序描述

该范例项目将跨场景地控制声音。
首先,在最初的场景中创建用于CRI相关物体和应用程序的声音控制脚本。其次,将脚本进行配置,以避免该脚本在最初的场景结束时被摧毁,并能够继续使用。
ScriptSample03_SoundManager对象控制应用程序中的声音。静态函数,ScriptSample03_SoundManager.PlayCueId()将被调用 以从任何场景中调用声音回放。
此范例将在各个场景开始时播放场景指定的音乐。This sample plays scene-specific music when each scene is started.
在音乐开始时,声音数据将被配置以交叉淡出淡入音乐。这防止场景切换时中段音乐。你也可以在跨场景时继续播放同样的音乐。

在场景切换时,维持声音相关对象有效的配置

你必须配置四个对象(组件)以避免它们在场景切换时被摧毁。
(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脚本为唤醒状态时,执行GameObject.DontDestroyOnLoad(this.gameObject)。
(5) 添加一些代码,以在ScriptSample03_SoundManager为唤醒状态时阻止多次生成(详细如下)。

依照这些步骤,你可以在场景切换时维持CRI相关对象以及 ScriptSample03_SoundManager.cs 有效。
步骤(5) 在再次选择最初的场景时,阻止了ScriptSample03_SoundManager.cs被重新生成。
同样阻止了 CRIWARE Library Initializer, CRIWARE Error Handler, 以及 CRI Atom 被重新生成。

ScriptSample03_SoundManager脚本的范例执行

SoundManager脚本需要执行以上的步骤(4)以及(5)。让我们将此范例用作例子。
GameObject.DontDestroyOnLoad(this.gameObject)代表了步骤(4)的执行。
基于isAwaked变量参数的GameObject.Destroy(this)代表了步骤(5)的执行

using System.Collections;
using System.Collections.Generic;
public class ScriptSample03_SoundManager : MonoBehaviour {
/* 当它为true时,将阻止ScriptSample03_SoundManager被再次生成 */
static private bool isAwaked = false;
/* ACB文件名 (cue sheet名称) */
public string cueSheetName = "CueSheet_0";
/* Cuesheet中,Cue名称的列表(cueSheetName) */
private List<string> cueNameList = new List<string> ();
private CriAtomSource atomSourceMusic;
static private ScriptSample03_SoundManager instance = null;
void Awake ()
{
if (isAwaked) {
/* 为防止多次生成,已创建的ScriptSample03_SoundManager之后将自我摧毁。
* 然而,ScriptSample03_SoundManager的组件 GameObject并没有被摧毁。
* 因此,在Unity Editor的hierarchy中有着同样名称的多个GameObjects。*/
GameObject.Destroy(this);
return;
}
isAwaked = true;
/* 从指定CueSheet中获取Cue信息,以创建Cue名称的列表 */
CriAtomExAcb acb = CriAtom.GetAcb (cueSheetName);
/* 创建Cue名称的列表Create a list of Cue names */
CriAtomEx.CueInfo[] cueInfoList = acb.GetCueInfoList ();
foreach (CriAtomEx.CueInfo cueInfo in cueInfoList) {
cueNameList.Add (cueInfo.name);
}
/* 创建用于背景音的CriAtomSource */
atomSourceMusic = gameObject.AddComponent<CriAtomSource> ();
atomSourceMusic.cueSheet = cueSheetName;
/* ScriptSample03_SoundManger在场景切换时将不会被摧毁 */
GameObject.DontDestroyOnLoad(this.gameObject);
instance = this;
}
static public void PlayCueId(int cueId){
instance.atomSourceMusic.Play(cueId);
}
}

两个相同的对象将显示于Hierarchy

当你在执行该范例后从ScriptSample03_GameScene to ScriptSample03_TitleScene返回时,你会发现某些对象的两个实例将显示于Hierarchy窗口。

cri4u_samples_criatom_script03_double_object.png

请忽视它们。它们不会引发问题。
当制止各个对象的多次生成时,Component(组件)自身将会被摧毁,然而它的父游戏对象将不会被摧毁,因此造成了这样的现象。
Inspector将显示第二个游戏对象为空白。该empty对象之后在场景再次切换时将会被摧毁。因此,程序将不会创建三个或更多的相同的对象。
如需阻止空白对象的显示,父游戏对象必须在制止多次生成时被摧毁。然而,这样的行为是危险的,因为这可能摧毁一个父游戏对象以及其他相连的组件。
我们推荐你仅允许一个父游戏对象的存在,以消除为各个组件阻止多次生成的必要。

如何能够让脚本从任何场景开始

该范例集中于场景变更时组件的摧毁,以及制止多次生成。因此,它必须从ScriptSample03_TitleScene开始。
" 从任何场景开始跨场景控制 " 范例描述了如何能够让脚本从任何场景开始。

用于各个游戏场景的脚本的描述

该范例从一个指定场景的脚本中发送音乐回放的请求。
ScriptSample03_SoundManager.cs存在于各个场景,并且一个静态函数,SoundManager.PlayCueId()也被定义了。因此,你可以从用于任何场景的脚本播放声音。
该范例的指定场景脚本非常简单。它们在场景开始时便开始播放音乐。

场景文件 Scripts/ScriptSample03_TitleScene.cs
using System.Collections;
public class ScriptSample03_TitleScene : MonoBehaviour {
private int SceneMusicCueId = 1;
private string nextSceneName = "GameScene";
/* 在第一次Update()前调用 */
void Start () {
/* 播放背景音 */
ScriptSample03_SoundManager.PlayCueId(SceneMusicCueId);
}
/* 显示并控制场景转换GUI */
void OnGUI(){
if (GUI.Button(new Rect(Screen.width-100,0,100,100), "change scene")) {
Application.LoadLevel(nextSceneName);
}
}
}

与高级范例的差异

该范例与CRI ADX的 [CriAtom] 进阶范例 中的 " [CriAtom] 不中断BGM的情况下切换场景 " 的差异如下。
两个范例都能够跨场景地播放声音。
该范例使用应用程序所创建的脚本,ScriptSample03_SoundManager。而" [CriAtom] 不中断BGM的情况下切换场景 "配置了Hierarchy,使CRI Atom Source在不编写脚本的情况下能够持续使用。
根据自身喜好,你可以使用任何一种方法。