08 · 音频系统
本章讲解 BGM、SE、Voice 和 Ambient 四类音频的控制。
音频类型
| 类型 | 全称 | 用途 | 特点 |
|---|---|---|---|
bgm | Background Music | 背景音乐 | 循环播放,唯一 |
se | Sound Effect | 音效 | 单次播放,可多个同时 |
voice | Voice | 语音 | 单次播放,与对话同步 |
ambient | Ambient | 环境音 | 循环播放,可多个 |
BGM 背景音乐
播放
bgm "Media/bgm_main.wav" volume=0.7| 参数 | 说明 |
|---|---|
| 路径 | 相对于项目根目录 |
volume | 音量(0~1,默认 1) |
停止
DSL 中没有专门的停止 BGM 命令。停止 BGM 需使用 C# API:
// 在 C# 场景脚本中
gameController.StopBgm(); // 同步
await gameController.StopBgmAsync(); // 异步或者在场景切换时,引擎会根据 DefaultAutoStopBgm 配置自动停止 BGM。
切换
直接播放新的 BGM 会自动停止旧的:
bgm "Media/bgm_town.wav" volume=0.7
// ... 小镇场景
bgm "Media/bgm_battle.wav" volume=0.9 // 自动停止 bgm_townBGM 是唯一的
同一时间只能播放一首 BGM。播放新的会自动停止旧的。
BGM 交叉淡入
在 StoryScript 子类内,可通过受保护的 _pipeline 字段发送命令实现 BGM 交叉淡入(渐出旧曲 + 渐入新曲):
await _pipeline.SendAsync(new BgmQueueCommand
{
Path = "Media/bgm_part2.wav",
Volume = 0.7f,
CrossFadeDuration = 2.0
});DSL 限制
bgm 命令只支持播放。队列、停止、交叉淡入等高级功能需要通过 C# API 调用。
SE 音效
se "Media/se_click.wav" volume=0.5SE 是单次播放的,可以多个同时播放(如点击声 + 提示音):
se "Media/se_select.wav"
say "你选择了攻击!" speaker="系统"
se "Media/se_hit.wav"
shake duration=0.3 intensity=10Voice 语音
Voice(角色语音)走独立的语音通道(单轨):同一时间只播放一句语音,新的会原子替换旧的。
方式一:独立语句
voice "Media/Voice/zhang_hello.wav" volume=0.9| 参数 | 说明 |
|---|---|
| 路径 | 相对于项目根目录 |
volume | 音量(0~1,默认 1) |
auto_stop | 前进时是否自动停止(true/false,默认跟随 DefaultAutoStopVoice) |
方式二:随 say 行内播放(推荐)
对话展示的同时播放该句语音,无需手动对齐:
say "你好!我是老张。" speaker="老张" voice="Media/Voice/zhang_hello.wav"单轨原子替换
语音通道只有一条。下一句 say voice= 或独立 voice 会顶替当前正在播放的语音——天然实现「翻到下一句就换语音」。
停止语音
当 say 之后没有下一句(例如对话结束、跳转场景前),语音不会自动被顶替,可用 stop_voice 主动中断:
say "再见了。" speaker="老张" voice="Media/Voice/zhang_bye.wav"
stop_voice // 立即中断当前语音
navigate "chapter2"回顾重播也会播放语音
say voice= 在回溯/前进重看一句时同样会重播该句语音(符合直觉:重看应听到同一句)。若重放场景不希望出声,可在 C# 侧控制。
C# API
// StoryScript 子类中,Ctrl 即 IGameController
Ctrl.PlayVoice("Media/Voice/zhang_hello.wav"); // 同步触发
await Ctrl.PlayVoiceAsync("Media/Voice/zhang_hello.wav"); // 异步
Ctrl.StopVoice(); // 停止当前语音
// 或在 SayAsync 中直接带语音
await Ctrl.SayAsync("你好!我是老张。", "老张", voice: "Media/Voice/zhang_hello.wav");Ambient 环境音
ambient "Media/amb_rain.wav" volume=0.4Ambient 是循环播放的,可以多个同时存在(如雨声 + 风声 + 篝火声):
ambient "Media/amb_rain.wav" volume=0.5
ambient "Media/amb_wind.wav" volume=0.3
ambient "Media/amb_fire.wav" volume=0.4
say "雨夜,你在壁炉旁取暖。" speaker="旁白"停止环境音
stop_ambient // 停止所有环境音
stop_ambient "amb_rain" // 停止指定环境音音频格式
| 格式 | 推荐 | 说明 |
|---|---|---|
| WAV | ✅ | 无损,引擎原生支持,加载快 |
| MP3 | ✅ | 压缩,体积小 |
| Ogg | ✅ | 压缩,开源 |
WAV vs MP3
- WAV——音质最好,加载最快,但文件大。适合短音效(SE/Voice)。
- MP3——文件小,适合长 BGM。
音频目录结构
Media/
├── Audio/
│ ├── BGM/
│ │ ├── bgm_main.wav
│ │ ├── bgm_town.wav
│ │ └── bgm_battle.wav
│ ├── SE/
│ │ ├── se_click.wav
│ │ ├── se_hit.wav
│ │ └── se_select.wav
│ ├── Voice/
│ │ ├── zhang_hello.wav
│ │ └── zhang_bye.wav
│ └── Ambient/
│ ├── amb_rain.wav
│ └── amb_wind.wav路径
音频路径相对于项目根目录,通常以 Media/ 开头。也可以放在 Media/Audio/BGM/ 等子目录中。
自动停止
引擎配置中有两个自动停止选项:
| 配置 | 默认值 | 说明 |
|---|---|---|
DefaultAutoStopBgm | true | 场景切换时自动停止 BGM |
DefaultAutoStopVoice | true | 对话切换时自动停止 Voice |
动手练习
给灯塔场景配上完整音频:
label lighthouse:
bgm "Media/bgm_main.wav" volume=0.6
ambient "Media/amb_rain.wav" volume=0.5
ambient "Media/amb_wind.wav" volume=0.3
se "Media/se_door.wav"
say "你推开了灯塔的门。" speaker="旁白"
say "风声和雨声渐渐远去。" speaker="旁白"
ambient "Media/amb_fire.wav" volume=0.4
say "壁炉里的火噼啪作响。" speaker="旁白"
// 战斗或事件
se "Media/se_hit.wav"
shake duration=0.3 intensity=10
// 离开时
stop_ambient
// BGM 会在场景切换时自动停止(DefaultAutoStopBgm=true)
transition "fade" duration=1.5下一步
音频掌握了!下一章学习 NVL 模式——让文本累积显示。