大家好,今天我为大家介绍的是利用Wwise、Unity和3D深度相机——Intel Realsense(以下简称Realsense)所制作的一个小游戏装置。该装置使用了Realsense作为感应器来获得玩家的实时位置,以Unity作为连接Wwise和Realsense的媒介,成功实现了人体动作与音频的互动。我将在这里整理我的开发过程并且与大家分享,希望能够对阅读者有所帮助。
1、选择开发工具
初期的作品灵感来源于众多RPG游戏中的Field Music,在这类角色扮演游戏中,玩家通过操控游戏中的人物来进行游戏,与游戏中的物体进行互动。通常游戏中的Field Music会作为区域独有的背景音乐出现,音乐的风格会带有强烈的区域特色,除此之外,在不同的区域之间转换时也能感受到音乐的淡入与淡出。因此,对作品最早的设想就是在现实生活中实现游戏中的Field Music,音乐除了要表现出不同的风格以外,也要根据人的位置变化而发生改变。考虑到Wwise所拥有的声音衰减(attenuation)以及RTPC功能,我决定用Wwise来实现声音的互动。作为一款音频中间件,Wwise需要与其他软件配合使用才能实现与人体动作的交互,考虑到感应器的搭载和程序运行的问题,以及和Wwise的整合功能,最终我选择了Unity。在选择感应器的时候,我将目标缩小至微软原本为xbox系列所开发的kinetic,以及intel开发的Realsense,这两者都可以对识别到人体的动作,并且都可以通过一个叫Nuitrack的SDK与Unity连接,由于Kinetic与新系统可能会互斥,最后我选择了Realsense。
到这里,作品的基本思路已经建立了,首先在Unity中建立一个Demo,用Wwise的功能去实现声音的变化,与感应器连接后,人的身体动作和位置变化可以直接控制demo中角色的动作和位置,通过这些动作与Demo中的声音发生互动,使人产生一种在现实中交互的错觉。
2、背景音乐的音量与衰减球
玩过RPG的朋友应该都会有这么一个印象:当操作你的角色走入一个区域时,便会听到这个区域所专属的音乐,尤其是在一些开放世界的游戏里,角色从A区域移动到B区域时,A的音乐会逐渐消失而B的音乐会慢慢出现,这样的效果可以通过Wwise的衰减球来实现。
我们在Unity中建立好3D模型之后,为安插音频建立一个Game Object(如图中红色的胶囊体)。
在Wwise中建立一个Event之后,返回Unity中添加Ak Ambient组件,选择Event和音频的触发方式,例如在下图中,我希望这个Unity场景被载入的时候就触发音频,所以在Trigger On的地方选择了Start,又在Name中选择调动了Snow这个Event。
到这里,就成功地给Unity中的物体添加上了音频。下面我们要开始通过调整衰减球来控制音量。在Wwise中找到被拖入到Snow的音频,在Positioning选项卡中对Attennuation进行调整。
从上图可以看到,我将音量的衰弱变化设置在这个范围以内,这个范围实际上是对应了Realsense的感应范围。Wwise和Unity用来表现距离的单位基本相同,但是这个距离单位与现实的距离单位之间并没有一个准确的换算,要将这两者对应起来才能实现人体与音频的互动。因此我在Unity中创建了一个人物角色模型,使用了Nuitrack提供的SDK将Realsense接入Unity,可以直接将Realsense所感应到的人体动作反应给Unity,达到控制角色模型的目的。
为了准确获得Unity的距离单位和现实单位的关系,一方面需要用代码实时监测发声源与角色模型之间的距离,另一方面要在现实的场地上测量出人与Realsense的实际距离。最后发现,Realsense和人的距离为2米以内时,可以将动作准确的反应给Unity,而在Unity所检测到的有效感应距离为14.2~17.5之间,为了保证触发的有效性,取了14.5~17的距离作为衰减范围。在演示作品时,将Realsense和投影屏幕放在同一个方向,体验者在范围内活动时,随着自己位置的变化,能够看到屏幕中的景色忽远忽近,也能从扬声器里听见背景音乐的音量忽大忽小,产生一种踏入特殊区域的奇妙错觉。
在Unity中,找到作为发声源的Game Object,在Inspector中将Ak Ambient中的Show Attennuation Sphere改成All_Events,就可以看见该场景中所有的衰弱球以及其对应的范围。
我们可以从图中清楚地看到衰弱球的红色区域,在实际操作中,Realsense所能判定的最远距离位于红色区域的边缘(上图浅蓝色点处),为了避免体验者进入区域时会迅速被Realsense感知到从而导致声音突兀地出现,角色模型的初始位置要放得远一些(上图红色点处),这样体验者在向前走时会慢慢进入判定范围,感受到从无声到有声的过程。
3、声音的碰撞触发与Ak Event
除了背景音乐的音量变化以外,在作品中还加入了利用碰撞来触发声音的互动模式,当角色模型与特定物体碰撞时,可以控制音频的播放与停止。要实现这样的互动,需要给物体添加适当形状的Collider,使它们在碰撞时能够产生反应,再根据碰撞的动作将信号发送给Wwise来触发音频的变化。触发音频的播放或停止相比起背景音乐的音量变化能够给人更加直观的互动感,因此我以碰撞触发作为这次音频互动游戏的机制核心。为了使体验者的行动合理化,游戏的背景设计成了魔法学院,而体验者作为一名学员可以通过学习魔法,并且参加魔法测验。下面将从“学习魔法”和“魔法测验”两个环节来说明音频的触发方式。
(1)“学习魔法”:触发播放声音
“学习魔法”的环节分为四个场景,每个场景限时30秒,体验者需要在规定的范围内不断移动,用身体去触碰“看不见的物体魔法阵”,当听见与背景音乐不同的声音时,便可以判断已经触碰到了“魔法阵”,这些声音大多是填充背景音乐的ME(Musical Effect),也有一定的概率会触发“魔法等级提升到x级!”的语音。因此在30秒内,体验者想要获得较高的魔法等级,就要尽可能多的去用身体去触碰这些“看不见的魔法阵”,以触发告知魔法等级提升的语音。
每一个场景中都提供了五个Game Object让体验者去碰撞,例如体在沙漠场景中学习土之魔法时,体验者站在规定区域的最远处时可以从前方的投影屏幕上看到五个被埋入沙漠中的建筑物残块,随着体验者不断向前进入了能够听到背景音乐的区域时,这些残块便会遍布在体验者的周围。当体验者通过移动不停移动自己的身体来控制角色模型和它们相撞的时候,就会触发播放出不同的声音。
为了实现“触碰——播放”这个动作,首先要在Wwise中建立一个类型为Play的Event。
在Unity中,为了确保两个模型可以产生互相碰撞而非互相穿透的效果,需要给其中一个物体添加代码,激活On TriggerEnter的状态。
根据游戏的设定,体验者通过感应器将控制角色去触碰五个特定的Game Object,因此我们将上述的代码附加给角色模型,在代码中设定void OnTriggerEnter(Collider other)可以使角色模型与任何带有Collider属性的Game Object发生碰撞而不是穿透的相互关系。之后,给五个可以触发声音的Game Object分别添加Ak Event组件,在Name的地方选择所对应的Event,在Trigger On的地方选择触发方式为AkTriggerEnter。
(2)“魔法测验”:停止播放
“在魔法测验”的环节,体验者同样需要与“看不见的魔法阵”互动。三个“看不见的魔法阵”围绕着中心点按照圆形的轨迹逆时针旋转,每一个“魔法阵”都搭载了同一首背景音乐的不同乐器演奏部分,体验者需要根据声音的来源判断“魔法阵”的方向,并且用身体与“魔法阵”碰撞来停止音乐的播放。
同样以沙漠场景为例,与“学习魔法”环节所不同的是,触发声音停止的Game Object都没有被勾上Mesh Renderer,也就是说它们虽然存在但是隐形了,这样做的是目的是让体验者知道无法从画面中寻找到“魔法阵”的位置,从而将注意力放到听觉上,通过声音的来源方向去寻找一直在移动的物体。
为了实现“触发——停止”,我们首先要在Wwise中创建一个类型为Stop的Event,然后选择会被停止的Event。
返回到Unity,与“学习魔法”环节所不同,我们需要让角色在碰触到特定物体后使其消失,因此需要在代码中进行控制,通常的方法是加入一行Destroy(other.gameObject),就可以让角色模型与特定的Game Object碰撞后使之消失。同样的,将Ak Event组件拖入特定的Game Object中,选择好指定的Event之后,在Trigger On的地方选择触发方式为Destroy,意为当这个Game Object消失时触发它所搭载的Wwise Event,这样就可以让该物体在消失时触发这个类型为Stop的Event了。
4、音频的随机性与游戏机制
由于本次的作品希望体验者能够依赖听觉来完成游戏,因此决定利用声音的变化作为游戏的机制。特别是在“学习魔法”的环节加入了现在的游戏普遍都有的随机性,以小概率出现的情况为诱饵,从而激发出游玩者的挑战欲。之前也已经提到,体验者需要利用不断移动身体去控制角色模型,使角色模型与五个特殊的Game Object相撞来触发音频的播放,这些音频通常都是填充背景音乐的ME,但也有可能是宣布魔法等级上升的语音提示。为了实现这个随机性,可以利用Interactive Music中的功能。
首先,在Interactive Music Hierarchy下面为每一个场景建立一个work unit,并且在这个unit下面建立5个Music Playlist Container,分别对应五个能够触发音频播放的Game Object。以森林场景为例,在这个场景中会被触发的ME是用竖琴演奏的琶音,因此我在ForestHarp的Work Unit下面建立了5个Music Playlist Container,分别对应了Unity中的五个植物模型。
将五个不同的琶音音频以Music Segment的形式分别导入到5个Music Playlist Container的下方之后,再把宣布魔法等级提高的语音音频同样以Music Segment的形式导入进去。由于游戏的设定,魔法的等级可以随机提升1-5级,因此在每一个Music Playlist Container中导入了一个琶音(如下图中的Inst6)和5个语音音频(如下图中的tree01~tree05,内容为“魔法等级提升到x级!”),五个Music Playlist Container中都完整包含了五个语音音频,这样会让体验者在碰撞到不同的Game Object时都有几率提升1-5级的魔法。
音频导入完以后,需要对随机的概率进行调整。以ForestHarp1为例,选中ForestHarp1的Music Playlist Container并且把窗口切换到Interactive Music,把它所包含的5个Music Segment拖入到Music Playlist Editor中,选择Random Step,在Weight中把琶音音频和每一条语音音频的出现比例调成50:1,由于我们不需要让音频自动反复播放,所以Loop Count全部调成1。比较关键的一点是Avoid Repeat要调成0,因为琶音的音频只有一条而语音音频有5条,如果使之前播放的音频不会第二次被重复播放,播放模式就会变成琶音→语音→琶音→语音……也就无法达到小概率出现语音音频的目的。(就是利用了随机的坑爹性激发一下人们的挑战欲望……)
以此类推,需要给每一个触发音频播放的Game Object建立一个Music Playlist Container。当Interactive Music部分的工作完成后为所有的ME建一个Event,再将之前的Music Playlist Container拖入Event中。最后,在Unity中找到对应的Game Object拖入Event。
5、声音的空间性与Game Object的移动
在“魔法测验”环节中,玩家需要去辨别发出声音而又随时在移动的三个“看不见的魔法阵”,然后移动身体去控制角色模型和它相撞,以达到使音乐停止的目的。为了使体验者能够在短时间内感受到声音从多个方向传来,并且能够意识到虽然它们各不相同但是却能组成一首完整的曲子,我将背景音乐的每一个轨道都生成了波形文件,再分组放入Music Segment中。例如海滨场景的背景音乐是一首Bossa Nova风格的曲子,我将乐器轨道从DAW中导出后分组放入了三个Music Segment中,这里并不需要对每个Segment的播放顺序做调整,在Music Playlist Editor中不需要拖入任何东西。
从上图可以看出来,一直连续的低音乐器和(风铃、沙锤、马铃和铃鼓)一组,贯穿全曲的鼓独自一组,剩下交替负责主旋律的乐器在一组,这样可以保证三个组在任何时候都有声音,不会让体验者产生错误的判断。由于组别的分配,各个乐器之间的平衡需要再次调整,可以直接通过Music Segment的菜单来调节。
之后,我们分别为这三个组建立新的Event,并且将它们拖入到Unity的Game Object中,并且把他们归到一个Game Object中,然后附加上能让它旋转的代码,这样可以让三个“看不见的魔法阵”能够围绕着一个中心逆时针旋转。
由于Unity的自带特性,发出声音的Game Object与倾听者的位置处于相对关系,因此在当把角色模型位于“看不见的魔法阵”的中心时,就仿佛处在一个立体声的空间里,所以也能够很容易地感觉到声音在移动,并且追踪发声源的方向。值得一提的是,由于人的反应有一定的延迟,并且“看不见的魔法阵”又一直处于移动状态中,因此在缺失了左后方和右后方两个现实发声源的双声道扬声器的环境中,体验者只能通过左前方和右前方的扬声器来判断发声源的位置,活动范围基本锁定在距离扬声器之间,而在佩戴耳机之后,体验者能够更加清楚地追寻到声音的来源,并且能够追着发声源的轨迹移动。
(国内观赏视频通道)
6、写在最后
Wwise和Unity在加入了外部感应器之后,让人体动作与音频的互动变得更加简单方便。然而感应器的性能在一定程度上会限制音频的自由创作,例如本次所使用的Realsense因为连接Unity后探测距离较短,因而无法在较大的场地中进行装置的演示,不能给声音的表演提供更佳的条件。但是Wwise+Unity+外部感应器的组合具有十分巨大的潜力,希望在将来能够有更出色的表现。
评论