以下内容为个人拙见,欢迎大家指正讨论。
Wwise在Unity中提供的方法中,并没有直接提供(看起来没有直接提供。。)暂停音效的方法。
在游戏中较为常见的需要停止音效(或者说控制音效播放状态)的场景,有在切换场景Loading读条时、某种游戏内置音乐播放器中等等。
音效控制场景建议
- 对于切换场景时(或氛围变化)的音乐切换,推荐在Wwise中创建切换事件来实现,这也是使用Wwise的原因之一,在Wwise中可以圆滑的处理音频之间的切换,也可以通过总线来控制一整组的音频。
- 对于单一音频的控制,则有以下几种方式(重点是第3条):
音效播放状态控制
-
Wwise的Unity集成包里提供的组件
AkEvent
该组件上面提供了
Stop()
方法- 优点:简单
- 缺点:不灵活,依赖于组件;没有暂停、恢复方法。
-
在Wwise工程中定义对应的Stop、Pause、Resume事件,通过发送事件来控制音效
// xxx指代某命名的音频 AkSoundEngine.Post("Stop_xxx"); AkSoundEngine.Post("Pause_xxx"); AkSoundEngine.Post("Resume_xxx");
- 优点:较为灵活,可以在任意地方调用
- 缺点:需要定义3倍于播放事件的操控事件,在Wwise中的工作量巨大;对同一音效的控制分离,难于管理
-
封装Wwise提供的方法来实现Stop、Pause、Resume三种控制
既然在AkEvent中有Stop方法,那么可以深入查看一下内部是怎么实现的,最后就找到了以下方法public static AKRESULT ExecuteActionOnEvent(uint in_eventID, AkActionOnEventType in_ActionType, UnityEngine.GameObject in_gameObjectID, int in_uTransitionDuration, AkCurveInterpolation in_eFadeCurve)
其中的参数
AkActionOnEventType
有以下几种类型
所以由此可以进行以下封装(其中WwiseLogger是自己封装的,方便release中剔除):
/// <param name="soundId">In <see cref="AK.EVENTS"/>.</param> public void Pause(uint soundId, GameObject soundSource = null) { // NOTE 经过试验,Wwise的暂停和恢复走的是计数机制,暂停多少次,就需要恢复多少次才能够正常恢复。 if (soundId == InvalidSoundId) { WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Invalid soundId.", soundId)); return; } var result = AkSoundEngine.ExecuteActionOnEvent(soundId, AkActionOnEventType.AkActionOnEventType_Pause, soundSource); if (result != AKRESULT.AK_Success) WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Pause wwise event with id <{0}> failed.", soundId), result); else WwiseLogger.LogMessage(WwiseLogger.LogLevel.Normal, string.Format("Pause event with id <{0}>.", soundId)); } /// <summary> /// Should call the same times with Pause. /// </summary> /// <param name="soundId">In <see cref="AK.EVENTS"/>.</param> public void Resume(uint soundId, GameObject soundSource = null) { // NOTE 经过试验,Wwise的暂停和恢复走的是计数机制,暂停多少次,就需要恢复多少次才能够正常恢复。 if (soundId == InvalidSoundId) { WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Invalid soundId.", soundId)); return; } var result = AkSoundEngine.ExecuteActionOnEvent(soundId, AkActionOnEventType.AkActionOnEventType_Resume, soundSource); if (result != AKRESULT.AK_Success) WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Resume wwise event with id <{0}> failed.", soundId), result); else WwiseLogger.LogMessage(WwiseLogger.LogLevel.Normal, string.Format("Resume event with id <{0}>.", soundId)); } /// <summary> /// Stop Audio. /// </summary> /// <param name="soundId">Wwise event id, defined in <see cref="AK.EVENTS"/></param> /// <param name="soundSource">发声源</param> /// <param name="transitionDuration">停止所需时间,单位为毫秒(ms)</param> /// <param name="curveInterpolation">音量变化曲线</param> public void Stop(uint soundId, GameObject soundSource = null, int transitionDuration = 0, AkCurveInterpolation curveInterpolation = AkCurveInterpolation.AkCurveInterpolation_Linear) { var result = AkSoundEngine.ExecuteActionOnEvent(soundId, AkActionOnEventType.AkActionOnEventType_Stop, soundSource == null ? gameObject : soundSource, transitionDuration, curveInterpolation); if (result != AKRESULT.AK_Success) { WwiseLogger.LogMessage(WwiseLogger.LogLevel.Warning, string.Format("Stop event with id <{0}> failed.", soundId), result); return; } }
需要注意的是,经过试验,wwise的暂停和恢复走的是计数机制,暂停多少次,就需要恢复多少次才能够正常恢复。
- 优点:非常灵活,无需定义大量时间
- 缺点:基于计数的暂停和恢复在复杂的游戏业务里可能会难以正确控制