利用 Wwise Meter 插件实现动画口型同步

音频编程 / 游戏音频

简介

这是徐若昊撰写的三篇技术系列博文的最后一篇。该系列博文主要分享《逆向坍塌:面包房行动》背后的声音设计。

  • 各位可点此阅读第一篇博文。其中深入探讨了如何利用 Wwise 驱动游戏中的过场动画。
  • 各位可点此阅读第二篇博文。其中探讨了如何为倾斜的 2D 俯视视角构建定制的 3D 音频系统以应对衰减上面临的独特挑战。

利用 Wwise Meter 插件实现动画口型同步

技术系列博文 | 第 3 部分

游戏中有很多这样的元素和瞬间,它们的玩法机制是由音频驱动的。借助 Wwise Meter 插件,我们可以实时获取准确的音频数据并回传给游戏引擎,以此来为多个音频系统提供支持。

跟很多其他以动漫为主题的游戏一样,《逆向坍塌》当中有很多剧情对白。其中有一部分在战斗中触发,但更多以 2D 叙事的形式呈现。也就是说,屏幕左右两侧的角色会进行问答式的对话。

img1

上图举例展示了游戏中的 2D 叙事机制。在截图的时候,角色 Mendo 正在说话。在触发语音的时候,会在角色头像之上播放口型动画。该功能由从 Wwise 获取的 Audio Volume 数据驱动。

游戏可利用 Audio Volume 数据将口型动画与语音同步,从而增强玩家跟角色互动时的沉浸感和临场感。这样叙事体验会更有层次,从而给玩家更强的代入感。

为了实时获取 Audio Volume 数据,我们使用了 Wwise Meter 插件。这个插件不仅易于使用,而且非常高效,可将 Wwise 中的音频数据发给游戏引擎。下图显示了主语音总线上的 Wwise Meter 设置。

img2

img3

在 Wwise Meter 插件内部,我们将 Speech_MeteringData RTPC 与之关联以将数据回传给游戏引擎。此 RTPC 会捕获在游戏中触发语音时产生的输出音量信息。我们将值限制在了 -48 ~ 0 之间,用以表示 Audio Volume 电平的范围。在语音音量达到峰值时,该值可能会超过 0。不过,在典型混音设置下最好避免这种情况,确保数值始终在 0 以下。

通过设置此配置,我们可以根据需要准确捕获 Audio Volume 数据,并将其传给游戏引擎,以此实现各种玩法机制。

上面的段落总结了 Wwise 端的设置。要在游戏引擎端使用这些数据,我们只需添加几行代码来检测音量范围,并将该数值转换为动画系统可用的数据。这里的动画代码写得比较简单,纯粹为了演示,因为每个游戏都会采用不同的动画系统或插件。

我们的游戏没有复杂的动画系统,角色的嘴巴只有 OpenClosed 两种状态。所以,我们可以直接使用三元条件运算来判断是否要让说话的角色张开嘴巴并做相应的动画处理(有关 GetGlobalRTPC() 的实现,请参阅前面的段落)。

bool bIsCharacterMouthOpen = (GetGlobalRTPC(“Speech_MeteringData”) > -48.0f  && GetGlobalRTPC(“Speech_MeteringData”) <= 0) ?true : false;

对于很多其他游戏(尤其是 3D 游戏),角色的骨骼绑定中可能包含关节和骨骼。对此,我们可以对动画设计师用于改变嘴巴开合程度的关节角度进行调整。该值通常用浮点数表示。比如,假定可通过 speakingCharacter.SetMouthOpenness(float mouthJointAngle) 获取该值,则嘴巴开合程度在 0 ~ speakingCharacter.MaxMouthOpenness() 度之间。

在本例中,我们要创建一个小型封装函数,以便提取参数修饰符的输出值,并根据需要在相应区域应用该值。

public float GetGlobalRTPC(string rtpcName)
{
    int rtpcType = 1;
    float acquiredRtpcValue = float.MaxValue;
    AkSoundEngine.GetRTPCValue(rtpcName, null, 0, out acquiredRtpcValue, ref rtpcType);

    if(acquiredRtpcValue >= 0.25 && acquiredRtpcValue <= 16)
    {
        return acquiredRtpcValue;
    }
    else
    {
        return 1.0f;
    }
}

除了对 RTPC 做全局设定,上述函数还会确保在检测到错误的值时忽略要设置的 RTPC 并重置为默认值 1.0f。

在这种情况下,我们可以使用以下函数来对上述代码进行优化以支持此功能:

public float SetMouthOpenessByWwiseAudio()
{
    float mouthOpennessToSet = 0.0f;
    float retrievedMeteringRTPCvalue = GetGlobalRTPC(“Speech_MeteringData”);

    if (retrievedMeteringRTPCvalue > -48.0f && retrievedMeteringRTPCvalue <= 0)
    {
        mouthOpennessToSet = speakingCharacter.MaxMouthOpenness() * Normalization(retrievedMeteringRTPCvalue, -48.0f, 0.0f));
    }

    speakingCharacter.SetMouthOpenness(mouthOpennessToSet);
}

当然,该函数会根据从 Wwise Meter 插件接收的 Audio Volume 数据准确设置嘴巴开合程度。这样可以确保口型动画与 Audio Volume 精确同步。

免责声明:本文中使用的代码段都是重构的通用版本,仅用于演示目的。其底层逻辑经验证可正常运行。不过为避开潜在的版权限制,示例中省略了特定于项目的 API 调用和函数。

徐若昊(Jater Xu)

音频程序员,技术音频

徐若昊(Jater Xu)

音频程序员,技术音频

徐若昊是一名经验丰富的音频程序员与技术音频,专门从事在Unreal和Unity中使用Wwise集成的交互式音频解决方案的相关工作,有着丰富的C++、虚幻蓝图和C#经验。他编写的音频系统是《家园3》、《The Chant》和《逆向坍塌:面包房行动》等备受赞誉的游戏中不可或缺的一部分。

评论

留下回复

您的电子邮件地址将不会被公布。

更多文章

Wwise和Unity的集成到应用

前言...

13.4.2020 - 作者:朱俊强

《使命召唤手游》的空间音频探索

当我们提起“空间音频”的时候,我们在聊什么?

15.6.2020 - 作者:腾讯天美工作室群

“不”字诀

由于社区中已经有很多更好的人在写声音设计和技术实现相关的内容,我借此机会写一篇与我2018年的博客《我理想中的工作环境:以游戏音频行业为例浅谈雇佣关系的人性化》关联的姐妹文章。...

21.6.2022 - 作者:戈登·麦格拉德里 (Gordon McGladdery)

为独立开发商提供免费 Wwise 授权 – 支持所有平台,无限声音素材(缘由及方式)

大家好!我来自 Audiokinetic 授权团队。四月份我制作了一段视频,今天我们来对此做下跟进。在 2022 年 4 月 1...

16.2.2023 - 作者:麦克•德拉默史密斯 (Mike Drummelsmith)

结合使用 Strata、Wwise 和 Unreal 构建沉浸游戏体验

在这篇博文中,我们将深入探讨如何使用 Strata 进行互动设计。为此,我们要在 Unreal Engine 5 工程中结合 Wwise...

31.5.2023 - 作者:蔡斯•斯蒂尔 (Chase Steele)

Jurassic World Evolution 2

Frontier Developments 由大卫•布拉本 (David Braben) 于 1994...

8.6.2023 - 作者:邓肯•麦金农 (Duncan Mackinnon)

更多文章

Wwise和Unity的集成到应用

前言...

《使命召唤手游》的空间音频探索

当我们提起“空间音频”的时候,我们在聊什么?

“不”字诀

由于社区中已经有很多更好的人在写声音设计和技术实现相关的内容,我借此机会写一篇与我2018年的博客《我理想中的工作环境:以游戏音频行业为例浅谈雇佣关系的人性化》关联的姐妹文章。...