这次 Jam 后为《月之回响》补充音频的过程中,发现 Godot 目前既没有很成熟的音频管理插件,也没有主流音频中间件的官方支持。
最后迫不得已,选择了自研这条艰辛的道路。
但如同游戏其他系统的自研过程一样,由自己研发的工具不仅可控性更强,也可以确保质量与品质。
————
由于过程中踩了不少坑,在此也与大家分享一些思路!
整个自研的音频系统包含两个大部分:
1️⃣ 负责配合游戏进度正确播放音乐的 Sound Director(音频导演)
2️⃣ 负责响应游戏各个部分发声请求的 Sound Bank Manager(音频库管理器)
它们分别负责与游戏中比较宏观的“高级游戏系统”(例如演出系统等),以及游戏中比较具体的“中低级游戏系统”(例如玩家角色控制器、敌人等)对接。
这里面 Sound Bank Manager 借鉴了音频中间件 Event 和 Event Bank 的设计思路,通过事件名的方式触发音频,而不是直接使用音频文件触发。
这样的好处是,一来可以解耦游戏代码与音频文件,方便管理;二来可以可视化的配置一些音频信息,统筹起项目的音频资源(例如可以指定音频播放的音量,或者最多只能有几个相同的音频在同时播放)。
————
为了能够接入一个比较底层的第三方音频插件,并且尽可能不对引擎的工作流做更改,因此这次音频事件的信息最终采用了一种「套壳」的方式,储存在了一个特化的引擎的音频资源中。
Godot 引擎中,通常采用某种 AudioStream 资源文件来播放音频,该文件直接和某个音频文件(mp3, ogg etc.)关联,从而实现音频的播放。
然后我自己实现了一个用于储存事件信息的特殊 AudioStream,这个 AudioStream 会内嵌一个真正的 AudioStream。
这样在用于播放时,它会把自己「伪装」成内嵌的那个 AudioStream,从而骗过音频系统,让其正常播放。
而不用于播放时,我可以通过自己的代码读取存在其中的信息。
令人头大的技术细节:「伪装」实际上是通过 override AudioStream 基类已有的一些方法实现的,让这些方法直接返回内嵌的 AudioStream 对应的方法即可。
————
关于这些开发更多的技术细节,如果大家感兴趣,我再择机分享。
不过这次大量自研系统,虽然踩了很多坑,但是也养成了阅读引擎源代码的习惯。甚至发现令人恐怖的 C++ 代码,在特定的情境下也没有那么吓人,还是可以阅读并理解的。
能够阅读引擎源码的好处,就是可以理解它运作的思路,并且找到官方处理一些问题的手法。情况合适时,这些手法大可以拿来自己用,从而仿制出和官方体验类似的编辑效果。
评论区
共 6 条评论热门最新