第 7 课

目录

通过 Wwise 专有 Event 实现回调

我们可以利用 AkEvent 和 AkAmbient 组件实现回调,也可将回调添加到 Wwise 专有 Event(事件)。该流程需要同样类型的信息(Callback Function 和 Callback Flag)。不过,在通过自定义脚本实现回调时,我们可以根据特定游戏机制或对象类型来定制回调,而不用受限于某一个具体的游戏对象。自定义脚本适合处理即时状况。比如,引用的游戏对象因为被《Wwise Adventure Game》的某个环境场景卸载而变得不可用。在前面的章节中,我们使用了来自 Music_Region Event 的 MusicSyncBar 的回调,以此调用了 RhythmActions 脚本并实现了 Tree(大树)的伸缩效果。“利用 AkEvent 组件设置回调”这种方式对只有几个选定游戏对象的情形来说效果挺好。因为不必编写脚本,直接拖放就可以。不过,随着素材数量的不断增加,“通过编写自定义脚本来实现回调”会便利很多。这样的话就不必在 AkEvent 组件中创建一长串回调条目。接下来,我们要通过回调通知来调节多个环境游戏对象的比例。首先,我们会利用 Wwise 专有 Event 属性来通过脚本发送 Music_Region Event。然后,对脚本进行扩展以使其包含 Callback 函数,进而通过 RhythmActions 脚本来调用场景中的各个游戏对象。

  1. 在 Unity 菜单栏中,依次转到 Audiokinetic > Certification > 301 > Lesson 7,然后选择 Callbacks on a Wwise-Type Event

    我们首先要创建脚本,然后再创建 Wwise 专有 Event 属性。

  2. 在 Hierarchy 中,选中 Wwise 游戏对象。

  3. 在 Inspector 中,单击 Add Component,然后搜索 PostMusic,接着转到 New Script 并单击 Create and Add

  4. 双击打开 PostMusic 脚本。

    首先,我们要使用 Wwise 专有 Event 类来创建和发送 Event。

  5. PostMusic 脚本之内、所有函数之外,键入 public Ak.Wwise.Event,以此声明一个 public 类型的 Wwise 专有 Event。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
        
    public class PostMusic : MonoBehaviour {
      public AK.Wwise.Event
        // 使用此函数进行初始化。
        void Start () {
        
        }
        // 每帧调用 Update 函数一次。
        void Update () {
        
        }
    }

  6. 在 AK.Wwise.Event 之后添加一个空格,然后将属性命名为 MusicEvent,最后添加一个分号 ; 来结束该代码行。

    public class PostMusic : MonoBehaviour {
      public AK.Wwise.Event MusicEvent;
    

    现在我们创建了 Wwise 专有 Event 属性,接下来可以在 Start 状态下发送 Event。这样的话一旦游戏初始化便会发送 Event。

  7. 在 Start() 函数之内,键入 MusicEvent.Post(gameObject);

    public class PostMusic : MonoBehaviour {
      public AK.Wwise.Event MusicEvent;
        // 使用此函数进行初始化。
        void Start () {
            MusicEvent.Post(gameObject);
        }
    

    对于组件,在为 Event 设置回调时,需要在发送 Event 的同时提供回调信息(Callback Flag 和 Callback Function)。另外,还要提供第二项输入参数 Callback Flag(第一项输入参数为 Game Object)。它需要通过 AkCallbackType 类来实现。对于 Post(),则可通过在 Start() 函数之内键入逗点 , 并后跟属性名称来直接添加 Callback Flag。

    [备注]

    注意,并非全部 Callback Flag 都与所有 Wwise Object 类型兼容。比方说,假如您想在 Destruction_VolcanicBoulder_Impacts Event 结束后进行回调,可以使用 AK_EndOfEvent CallbackFlag。但是,因为该 Event 没有播放 Music Segment,所以并不会调用 AK_MusicSyncBar。

  8. 在 gameObject 之后,添加一个逗点 , 和一个空格,然后键入 AkCallbackType.AK_MusicSyncBar;

    void Start () {
        MusicEvent.Post(gameObject, AkCallbackType.AK_MusicSyncBar);
    }

    这样便会检查 AkCallbackType 类的 AK_MusicSyncBar Flag,并将其添加到所发送的 Event。不过,对于 Post 函数,我们还要专门以 uint 属性类型的方式来发送 AK_MusicSyncBar。

    [备注]

    利用 C# 编程语言(本项认证课程中所用编程语言),我们可以在整数 (int) 属性类型中存储不含小数位的数字。该属性类型既可存储正数也可存储负数(取值范围为 -2,147,483,648 ~ 2,147,483,647)。不过,假如要确保所有数字都是正数,您可以添加无符号前缀 u,将其设为无符号整数 uint(取值范围为 0 ~ 4,294,967,295)。

    您可以通过在 CallbackType 属性之前在括号中键入新的属性类型来转换属性。

    [技巧]

    将某一属性转换为另一类型的过程称为类型转换。

  9. 在 AkCallbackType.AK_MusicSyncBar 之前插入 (uint)

    MusicEvent.Post(gameObject, (uint)AkCallbackType.AK_MusicSyncBar);

    您有没有注意到 Post 函数下方显示了一条红色短线?

    这是因为目前尚未声明在 Wwise 回叫 Unity 时调用哪个函数。接下来,我们重命名 Update() 函数。这样可以避免 Unity 自动调用它,以此将其设为 Callback 函数。

  10. Update() 重命名为 CallbackFunction()

        // 每帧调用 Update 函数一次。
        void CallbackFunction(){
        
        }

    为了避免引起误解,我们来同时删除上面有关 Update() 函数的备注。

  11. 删除备注“// 每帧调用 Update 函数一次。”。

    void CallbackFunction(){
        
    }

    接下来,我们将函数名称添加到 Post() 函数中。

  12. MusicEvent.Post(gameObject, (uint)CallbackType 之后,键入 , CallbackFunction 以将 CallbackFunction 作为参数添加到函数中。

    MusicEvent.Post(gameObject, (uint)AkCallbackType.AK_MusicSyncBar, CallbackFunction);

    我们注意到,CallbackFunction 下方的红色短线消失了。

    在 Post() 函数之内添加回调函数后,Wwise 声音引擎一旦遇到所选 Callback Type 便会调用该回调函数。因为我们选择了 Callback Type AK_MusicSyncBar,所以 Wwise 声音引擎将会在进行到音乐中每一小节时调用回调函数。

    不过,Wwise 声音引擎还需要回调函数能够接收有关回调通知的信息。所以,CallbackFunction 必须要能接收该信息。也就是说,不管需不需要,都得在函数的圆括号之内声明若干变量。

  13. CallbackFunction() 的圆括号之内,键入 object in_cookie, AkCallbackType in_type, object in_info

    void CallbackFunction(object in_cookie, AkCallbackType in_type, object in_info){
        
    }

    如此一来,便可获取有关回调的信息,比如它属于哪种 Callback Type。因为我们只会接收一个回调(即 MusicSyncBar),所以目前并不需要这些参数。

    [技巧]

    如需进一步了解 Callback 函数中的这些输入属性,请参阅 Wwise SDK 文档

    现在我们成功地设置了回调,不过目前尚未指定要拿它来做什么,CallbackFunction() 仍是空的。最终,我们需要在游戏中调用各个 RhythmActions 组件。为了本次演示,我们在 GameManager 中创建了一个所有 RhythmActions 组件都要检测的函数。GameManager 脚本是个单一实例。也就是说,只能有一个这种实例,并且不会在游戏当中销毁。所以,我们可以确定该函数始终都是可用的。

    在运行时将 RhythmActions 脚本实例化之后,会自动创建与 GameManager 的关联。这样就可以通过 GameManager 进行统一调用。

  14. 在 CallbackFunction() 函数之内,键入 GameManager.PushRhythmAction();

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class PostMusic : MonoBehaviour {
                          public AK.Wwise.Event MusicEvent;
        // 使用此函数进行初始化。
        void Start () {
            MusicEvent.Post(gameObject, (uint)AkCallbackType.AK_MusicSyncBar, CallbackFunction);
        }
        void CallbackFunction(object in_cookie, AkCallbackType in_type, object in_info){
            GameManager.PushRhythmAction();
        }
    }

    好样的!我们完成了本节课程中的所有脚本编写步骤,现在可以保存脚本了。接下来,我们要将 Wwise 专有 Event 属性指派给 Music_Region Event。

  15. MusicEvent 属性中,依次展开 Events > Music > General,然后双击 Music_Region

    接下来,我们可以将 RhythmActions 脚本指派给场景中的游戏对象。假如游戏设置允许,它们就会随着音乐节奏舞动。

    [备注]

    游戏世界环境(Desert、Forest 等)当中所用的有些游戏对象设成了静态。假如游戏对象被设为静态,在运行时将无法随着音乐节奏舞动。为此,可在 Inspector 顶部取消选中游戏对象的 Static 设置。

  16. 在 Hierarchy 中,选中所有以 TrainingArea_ 为开头的游戏对象。

    通过选中这些游戏对象并选择 Add Component,可将组件同时添加到选中的各个对象。

  17. 在 Inspector 中,单击 Add Component,然后搜索并选中 RhythmActions

    现在,我们成功地通过自定义脚本将 RhythmActions 添加到了多个游戏对象,从而将回调这一核心功能巧妙地整合到了游戏中。下面来试试吧。

  18. 进入 Play 模式。我们注意到,刚才选中的所有对象都会按照音乐的速度舞动。

    您可以自由地调节游戏对象的伸缩幅度,并将更多 RhythmActions 脚本添加到场景中的其他游戏对象。

回调系统设置好了,而且能够正常运行。在 Region_Music Event 进行到 Music Segment 中的小节时,将会调用所有与 RhythmActions 脚本绑定的游戏对象。为了实现这一点,我们在 PostMusic 脚本中设置了 Callback,并以此调用了 GameManager 中的 PushRhythmAction() 函数。相对于前面的章节,我们在此阐明了如何通过代码来设置回调,并以此来灵活地处理卸载的对象,或者快速地将回调添加到诸多对象。