序言
简介
音乐系统概述
正文
        NPC 的哼唱与音乐同步
            《一剪梅》– 随机哼唱的词牌乐曲
           《望海潮》– 在音乐间歇或与场景音乐正拍同步的侍童哼唱
        3D 词牌曲与 2D 背景音乐的“合奏”
        背景音乐与 NPC 的 3D 诵经声同步
       场景音乐结合实时动态的演变
        避免频繁切换音乐带来的干扰:不同区域的主题场景音乐间的平滑过渡
              场景音乐与无声时段的处理
音频技术细节
         Wwise 工程的组织结构
         乐坊音乐
         战斗音乐
         实现 Conductor 音乐控制系统和其他游戏机制之间的复杂互动
结语
序言
除了靠背景音乐还有没有别的途径能增强游戏的沉浸感和临场感?作为音乐监制和首席作曲家,在项目刚开始我就这样问自己。
简介
《射雕》是一款由金庸的武侠小说《射雕英雄传》改编而来的以宋朝(960-1279 年)为背景的开放世界 MMO 游戏。据历史记载,宋朝是个经济文化空前繁荣的盛世,同时它也见证了音乐的多元化发展。其中最受欢迎的要数风行于勾栏瓦舍(民间演艺场所)的传统民乐表演。
另外,研究表明,跟中国古诗相比,中国词牌(诗句遵循固定的结构和韵律,严格规定了节奏和音韵体系)更具音乐性也更容易音乐化。当时,这种形式经常被用作文化推广的手段,歌词多反映时政局势、文化理念和社会情绪。

游戏中为词牌奏乐的中国民间乐坊
所以,我就开始设想能否以 3D 音乐的形式在游戏中再现这些民间乐坊,并为其设计特定的舞台,同时根据游戏的时代背景或玩法剧情为所选的词牌谱写新的乐曲。藉此重现古代老百姓的日常生活,让玩家获得一种亲历旧时光的沉浸体验。
最终,我们选用了以下中国传统乐器(上图从左到右):筚篥、箫、小镲、古琴、琵琶、缶、大鼓、碗琴、拨浪鼓/小笛(双人演奏)、碰铃/古筝(双人演奏)、尺八、方响、笙、檀板,另有偶尔伴以箜篌与三弦。
这些乐器全部以 3D 的形式呈现,并采用通过 Wwise 模拟的自然衰减曲线;因此,对于在游戏中不小心迷路的玩家来说,它们也可以成为一种“据此提供基于声音的导航”,或者也可以作为彩蛋供那些无意中发现它的玩家探索。
在构思完民乐团的概念后,接下来的首要关注问题便转向了如何呈现这些词牌曲以及游戏中播放逻辑框架的整体设计。而各位或许已经开始有了一些疑问,比如:
- 这些 3D 词牌乐曲会不会跟 2D 背景音乐的播放逻辑发生冲突?
- 在玩家靠近这些乐坊的时候,背景音乐会发生怎样的变化?
- 等等
在音乐设计方面,我其实从游戏开发前期就开始着手设计全局音乐系统,并决定突破传统国风游戏音乐的常规作曲范式、播放规则以及表现形式。
本文将从上述提到的 3D 词牌曲的主题说起。在此,我们以下面列出的主题为例详细说说交互音乐系统设计的功能实现以及音频程序员的技术支持。
- 3D 词牌曲与 NPC 的 3D 随机哼唱的同步机制
- 3D 词牌曲与 2D 背景音乐的“合奏”同步
- 背景音乐与 NPC 3D 诵经声的同步
- 场景音乐结合实时动态的演变
- 避免频繁切换音乐带来的干扰:不同区域的主题场景音乐间的平滑过渡
音乐系统概述
经过初步探索,我们发现 Wwise 一般会通过全局 State 或 Switch 来控制音乐 Event。这种方式对我们的需求来说不太灵活。我们的需求包括:
- 剧情和非剧情音乐之间不应有明确的界限。前者可以转变为后者,后者也可转变为前者。另外,有些主题元素可以是剧情性的,有些则不可以;这些元素本身可基于关卡标记、游戏代码甚至过场序列动态地出现和消失。
- 游戏涵盖庞大而精细的开放世界,其中设有各种角色、场所和遭遇。为此,音乐系统要根据实际情形动态设定优先级、安插无声时段并管理暂停期间的行为。
- 游戏是由书改编的,所以叙事非常重要。游戏中有很多精心打造的线性序列和过场动画,它们要跟音乐同步,甚至要精准地压在拍子上。
显然,这需要为多个 3D 音乐发声体、回调、优先级系统以及各种编辑工具提供支持。所有这些都可通过我们的 Conductor System 实现。该系统由三个核心组件构成:
- World Conductor。这个全局实体负责根据数据表中定义的规则对音乐主题的播放进行排队、排序和调度。比如,场景音乐主题一般优先级较低,而且在战斗期间会暂停播放。除此之外,World Conductor 还可将音乐回调传到音乐系统之外,以实现游戏玩法的同步(比如在过场动画当中)。
- Music Conductor。这些实体负责管理音乐主题的控制流程,并对同时播放的 Music Source 进行协调。在必要时,其还可维持内部状态。比如,我们可以保存音乐主题的最后播放位置以便稍后继续播放(比如在请求播放更高优先级的主题时)。
- Music Source。这些实体负责执行来自所属 Music Conductor 的命令,并将其映射到 Wwise API 调用。事实上,每个 Music Source 都可放在游戏世界中的任意位置。另外,Music Conductor 的第一个 Music Source 始终被视为引导轨 – 该音轨用于收集回调。在必要时,所有其他 Music Source 都要与之同步。
这是一种非常简单的分层架构。其中,低级别实体不了解高级别实体的任何信息。另外,Music Conductor 和 Music Source 要分别实现各自的 Blueprint Interface。这给刚开始的设置增加了一定的难度,但也让我们能完全覆盖音乐播放逻辑,同时保持与 World Conductor 的优先级和调度机制完美融合。比如,在某一时刻,我们要添加虚拟乐器来让玩家能够与之互动,并演奏一段贴合当前播放的音乐主题的旋律。为此,我们只需创建一个专门的 Music Source。它本身并不播放音乐,但能识别所属音乐主题的当前和弦,并内嵌有简单的启发式算法,可根据当前和声触发随机音符。
音乐系统的行为可通过 Unreal 的数据素材和数据表进行配置。因为 World Conductor 把实现细节跟游戏代码分开了,所以很容易就可与过场动画和对白系统集成、构建调试 UI 并添加关卡标记。而且,World Conductor 的状态机会动态处理所有过渡,而不管音乐控制请求是从哪发出的。在此基础上,我们构建了一个名为 Conductor Sequencer 的系统。本质上,它允许以类似于追踪器的方式对发送到 World Conductor 的命令进行排序。后来,我们在音乐需要严格遵循控制流程的小型脚本化场景中广泛运用了这一功能。
正文

将 NPC 的哼唱与音乐同步
《一剪梅》– 随机哼唱的词牌乐曲
这首词牌通过写景寄情,唤起听众的情感共鸣,情感真挚而又不失婉约。以下是我们在设计时确定的一些核心要点:
- 旋律需通俗易唱、朗朗上口(便于百姓传唱);
- 适合孩童 NPC 跟唱;
- 避免中国传统乐器过于细腻的纹理,保留朴素感。
玩家和 NPC 角色的哼唱都会随机触发并与词牌曲实现同步,为此,我们还特别邀请了演绎不同角色的配音演员来分别演唱一些段落。
在下面的游戏实录中,各位可以听到我们把乐器和人声放在了不同的位置(见下图),来模拟“坊间各户人家经常聚在一起奏乐唱歌”的情景;家里的小孩 (NPC) 甚至还会一边放风筝一边跟着哼唱一两句。此外,这也是为了表现随着音乐世代相传的文化意蕴,为这片区域更是增添了一丝朴实的人间烟火气。

由于各个角色模型之间的距离非常近,玩家无论向何处移动都能听到来自不同方向的同步音乐分轨。
《望海潮》– 在音乐间歇或与场景音乐正拍同步的侍童哼唱
在大部分情况下,跟随玩家的 NPC 通常只有在战斗环节才会与玩家互动。不过,在我的设计理念中,跟随玩家的 NPC 由于始终保持着孩童形象,那么他一定会偶尔哼些小调,有时还会调皮淘气。所以,我决定赋予他一些“灵性”,添一丝现实生活的气息。。
在下面的游戏截图中,各位可以听到主角旁的侍童会时不时随机哼唱几句,但又能都精准地压在节拍上。

3D 词牌曲与 2D 背景音乐的“合奏”
在中都场景中,乐坊会演奏与该区域的背景音乐同步的词牌曲(例如《无题》)。然而,这也引出了一个潜在问题:它会不会跟背景音乐发生冲突?
对此,我遵循了以下设计原则:
- 为词牌乐曲的播放设置时间限制。
- 在同一时间段内将背景音乐与词牌乐曲同步播放。
- 根据词牌曲的曲速、调性与配器(避免使用过于密集的相同乐器)编制来创作背景音乐,让它们自然地交织在一起,相互之间无缝衔接。
- 基于距离控制背景音乐的音量。
简单来说,最终在玩家靠近 3D 对象时,背景音乐会逐渐降低音量,并将焦点转移到 3D 对象上。另外,因为两首乐曲的速度、音调与和声行进完全相同,所以不会有音乐突然被切换的听感。在玩家离开之后,两首乐曲仍可独立存在。过渡非常自然,不特别注意的话很难察觉。同时,这也模糊了剧情和非剧情音乐之间的界限。
游戏中的很多其他地方也都设计了类似的同步规则。

将背景音乐与 NPC 的 3D 诵经声同步
灵泉寺是一座历史悠久的佛教寺庙,在游戏中也有着重要的地位。它本身给人的感觉比较神圣,不过我想融入一些新鲜元素,而非单纯依赖主题背景音乐营造出宁静与庄重感。那么,除了寺庙里僧侣经常敲打的木鱼和钟铃声,还有其他特别的声音元素可以使用吗?
后来,我想到了将僧侣们日常诵读佛经的声音融入其中。
为此,我请了一位录音师前往中国的佛教寺庙,实地录制并收集一些僧侣诵经的音频样本。在收到录音之后,我做了以下处理:
- 将诵经声的音调与背景音乐同步。
- 将诵经声的曲速与背景音乐同步。
- 在当前音乐的强拍上,随机触发诵经声片段。

确保场景音乐与实时动态同步演变
有些玩家难免会从早上玩到中午,或者从下午一直玩到晚上;也就是说,其连续游戏的时间可能会跨越不同时段。由于游戏内时间与玩家本地时间同步,此类型游戏通常会为各个时段播放不同的乐曲。然而,这种“明显且频繁的音乐切换”是我们希望避免的。为此,我决定让整体场景音乐主题动态地演进和变化,并在相同音轨内随着时间的推移融入更多变化。
- 设置早晨、下午和晚上三个时段的音乐变换。
- 设置相同音频文件内的所有音乐分轨的变换。
- 在维持动态分轨时兼顾连贯性和变化性。
- 设定某一时段内的音乐播放为完整版本,作为其核心形态。
同样,玩家在游戏过程中可能不会察觉到音乐切换的痕迹,但会产生一种“这个场景中的音乐在下午好像变得更加丰富了”或“那个场景中的音乐在晚上好像变得更加轻柔了”的感受。

避免频繁切换音乐带来的干扰:不同区域的主题场景音乐间的平滑过渡
以上所述主要介绍了在玩家处于相同场景或固定情形下的音乐随之发生的变化。而除此之外,我们也针对玩家因剧情推进或自由探索而从一个地点步行或瞬移至另一个地点时的情况,专门设计了音乐播放逻辑。
简单来说,我不想让玩家每次进入新的区域立马就感受到音乐的切换。这种重复性的处理方式最终只会让玩家感到无聊和疲惫。尤其考虑到部分玩家可能会频繁误入并马上离开某个区域,因此我们在音乐切换机制中设置缓冲识别时间和空白间隔。比如:
对于常规场景:
- 在系统发现玩家在新的区域待了一段时间后,才会激活当前音乐动作。
- 在无声间隔时间达到一定秒数后,才会触发新的音乐动作。
对于一些特殊场景:
- 逐渐减少当前音乐的部分乐器,继续播放剩下的部分而不做切换。
- 在玩家进入新的区域时,触发专属的短插播乐句。
在像《射雕》这样的开放世界游戏中,玩家可能并不希望每时每刻都听到背景音乐,所以在音乐中插入 30% ~ 40% 的无声时段也能有助缓解听觉疲劳,也能让其他更重要的音乐变得突出。
场景音乐与无声时段的处理
关卡标记可定义音乐音量,告诉 World Conductor 该区域要播放什么音乐。按照约定,我们决定不进行循环播放,让玩家享受一段安静的时光,直到稍后重新开始播放音乐。在暂停播放的时候,音乐系统会通知游戏可以播放特定语音 Event。比如,哼唱或吹奏刚刚播放过的音乐中的旋律和主题。
而且,World Conductor 还知道当前的游戏内时间,并可安排在早上、白天和晚上播放相应版本的主题音乐。另外,系统还提供有可配置的无声时段,在此期间不会播放任何场景音乐。
除此之外,还可定义排除区域来在玩家靠近特定位置时平滑淡出区域音乐,以突显正在发生的事情的重要性或为即将发生的事情留出空间。
区域音乐可能会因战斗或其他遭遇而中断,因为它的优先级一般是最低的。在这种情况下,World Conductor 会暂停当前播放的主题,并在明确停止高优先级的主题后继续播放。说到这里,要注意暂停的 Event 在 Wwise 中仍被视为活跃声部,因为其会影响自动闪避。
另外,World Conductor 还能实现跟 Wwise 中类似的复杂过渡。比如,与小节基本同步或播放插播乐句来掩饰过渡。这些过渡可在数据表中进行配置。
音频技术细节
Wwise 工程组织
每个为游戏创作的音乐主题都有自己独立的层级结构。比如,Work Unit 按音乐的用途分类(如战斗音乐、场景音乐或线性序列音乐等)。各种音乐会发送到各自的总线以便实施混音,并确保在需要的时候有选择地应用自动闪避。

将各种音乐主题相互分开增加了在游戏引擎端实现的难度,因为其需要管理过渡、插播乐句、淡入淡出及无声和同步。后面两个对我们尤其重要,因为它们有特殊的要求,而这些很难通过单个 PlayingID 管理的音乐来实现(稍后会详细介绍)。
简单来说,我们大大简化了 Wwise 工程,很多东西都通过代码来实现。音乐的实现因其类型而异,有时这种差异可能会很大。比如,有些主题采用典型的 Switch Container 结构,有些则可能依赖代码实现循环播放。就音乐系统来说,它们采用不同的 Conductor 类。我会在下文试着对其中一些做说明。
乐坊音乐
这种剧情音乐在游戏中以虚拟乐坊在给定时间演奏乐曲的形式呈现。玩家可以进入聆听模式。这时摄像机会围绕角色运镜。下面是详细的要求:
- 所有乐器或人声都可单独放到场景中。
- 音乐主题不会循环播放。
- 虽说是单人游戏,但玩家必须在给定时间聆听乐坊演出。这样可以确保所有玩家(即便在演出中途加入)听到的内容大致相同。
我想到两种方法可以在多个空间位置之间完美同步剧情音乐:管理一系列 3D 辅助总线发送,或将每种乐器作为单独的 Event 来播放。我们最终选择了后者。我不记得具体原因了。观察发现,若在调用 AK::SoundEngine::RenderAudio 之前发送一组长度相同的 Event,其会一直同步播放。需要注意的是,这些 Event 必须采用相同的流播放、虚拟化和寻址表设置。最终,我们在整个工程中借助 WAAPI 解决了这一问题。
另外,Wwise 对 SeekOnEvent 动作有诸多限制,而我们又要使用其来同步音乐播放位置。最主要的是,循环 Event 无法执行寻址。所以,所有乐坊乐器都是等长的一次性 Event,它们会在需要时由 Conductor 循环播放。
战斗音乐
游戏中有两种战斗音乐:BOSS 战和小型遭遇战。
我先说说前者。它的 Conductor 采用典型的 Wwise 实现模型(包括 Switch Container 和过渡)。BOSS 战总是按照给定的阶段单向推进;比如,开局 → 阶段 1 → 阶段 2 → 胜负。为此,我们创建了通用的 "Music_Part" Switch,并约定了每个阶段意味着什么。
与 BOSS 战不同,小型遭遇战没有阶段划分;其音乐以无限循环的形式呈现。就作曲而言,音乐被分为具有鲜明特征的乐段,其相互之间采用简短的过渡衔接。音乐由淡入开始,并以淡出结束。Conductor 会追踪播放位置,以便稍后从停止的地方重新开始播放音乐。不过,在这里,音乐会在之前停止的地方之后的标记位置重新开始播放。这些标记刚好放在乐段过渡开始的地方。通过在这些过渡位置由淡入开始播放音乐,可进一步强化每次遭遇时的渺小感和重复感。

由于此类音乐需要寻址,所以循环播放由 Conductor 统一管理。
说到淡入,Wwise 并没有提供通过代码控制淡入的 API。不过,我们可以通过执行以下步骤来解决这一问题:发送 Event → 立即暂停 → 在调用 RenderAudio 之后等待一帧 → 按照给定过渡时长恢复播放。若不等待一帧,Wwise 会将命令序列合并处理,并误认为 Event 应保持播放状态而非恢复。我不记得具体原因了,但当时确实有必要重构这一变通方案,改用带插值时间的 RTPC 来实现淡变。
实现音乐和其他游戏机制之间的复杂互动
到目前为止,我们一直在探讨不同类型音乐主题的内部运作机制。接下来,我们将通过一些示例说明系统如何实现音乐和其他游戏机制之间的复杂互动:
- 其中一个关卡中的寺庙有个祭坛。它会响应 Wwise 的回调,并触发微弱的声音。
- 在户外穿行时,玩家可以找到一个小村庄,村里有个角色正在唱歌,歌曲与当前播放的背景音乐完美同步。
- 有个鼓手在演奏,将玩家的注意力吸引到某个位置。到达该地点后,开始播放过场动画,展示比武较量。这个剧情性的鼓声循环逐渐变为非剧情性的过场音乐,最终以一声锣响收尾。因为锣声标志着较量结束,所以我们必须确保击打动作与视觉画面完美同步。为此,我们选择了从 World Conductor 向关卡序列播放器发送回调。该播放器会在收到回调后跳到下一过场片段。所述回调最初是作为以特殊名称标记的 Wwise 音乐提示创建的。
在所有这些示例中,功能都是通过 Conductor API 实现的;游戏代码无需了解关于 Wwise 的任何信息。
结语
本文对我们的 Conductor 交互音乐系统做了比较系统性的概述,着重阐释了其在增强玩家沉浸感、增进情感互动以及提升整体游戏体验方面的核心作用。我们在开发过程中始终致力于“感性”与“理性”的交织:确保各类音乐不仅富有感染力,又能与给定场景的内在逻辑协调一致。最后,希望各位在阅读这篇文章的时候能感受到跟我们在开发当中一样的乐趣。

 
                            
评论