Skip to content

音效设计指南

这不是一个单独的配方,而是一份技巧合集——教你用 Yumina 的音频系统打造完整的听觉体验:跟随场景切换的 BGM、关键词触发的音效、循环的环境音、丝滑的交叉淡入淡出,以及从自定义 UI 和 AI 叙述中控制音乐的各种方法。


概览

Yumina 的音频系统有多个入口,可以从不同层面控制声音:

控制方式在哪设置特点
播放列表自动播放音频 标签页最简单,进入世界就有背景音乐
条件 BGM音频 标签页变量/关键词/回合数满足条件时自动切歌,不需要写行为
行为 + 播放音乐动作行为 标签页场景切换时交叉淡入淡出,配合修改变量和开关条目一起用
AI 音频指令AI 在回复里写 [audio: ...]AI 自己决定什么时候播什么,最灵活也最不可控
消息渲染器 API消息渲染器 标签页从自定义按钮触发,适合做点歌机等交互 UI

本指南按 7 个模式逐一讲解,你可以按需取用,也可以组合使用。


模式 1:基础 BGM 设置

你要做的

让玩家一进入你的世界就听到背景音乐,循环播放,不需要任何额外操作。

一步步来

第 1 步:上传音频轨道

编辑器 → 音频 标签页 → 点击「添加音轨」

字段填什么为什么这样填
显示名称主题曲给你自己看的
IDmain_theme后面所有引用都用这个 ID
类型BGM背景音乐
音频文件上传你的 .mp3.ogg 文件支持常见音频格式
循环开启BGM 通常需要循环
音量0.7不要太大声,留出空间给音效和环境音
淡入2进入时渐渐响起,不突兀

想多放几首?重复上面的步骤,创建多条音轨。比如 explore_bgm(探索曲)、battle_bgm(战斗曲)、town_bgm(城镇曲)。

第 2 步:设置播放列表

同在 音频 标签页,找到「BGM 播放列表」区域:

字段填什么为什么这样填
曲目列表选择 main_theme(如果有多首就全选)列表里的曲目会按顺序播放
播放模式loop(循环)或 shuffle(随机)loop = 按顺序循环;shuffle = 随机打乱
自动播放开启进入世界就自动放
等待首条消息关闭(或根据需要开启)开启的话,音乐会等到玩家发出第一条消息后才开始
间隔秒数0(或 2两首曲子之间的停顿,0 = 无缝衔接

效果

玩家进入世界 → 音乐自动响起(带 2 秒淡入)→ 一首放完自动放下一首 → 列表放完从头再来。

只有一首 BGM?

如果你只有一首曲,直接把音轨的 loop 打开,播放列表里只放它一首就行。甚至可以不设播放列表,直接用条件 BGM 或 AI 指令来控制。


模式 2:场景切换时 BGM 交叉淡入淡出

你要做的

玩家从「村庄」移动到「地牢」时,村庄的悠扬音乐渐渐变小,地牢的阴森音乐渐渐变大——两首曲子有一小段时间同时播放,过渡丝滑无缝。

原理

玩家点击「前往地牢」按钮
  → 行为触发:修改变量 location = "dungeon"
  → 同一行为里的播放音乐动作:crossfade 到 dungeon_bgm
  → 旧曲目淡出 + 新曲目淡入,过渡时长 2 秒

一步步来

第 1 步:准备音轨

音频 标签页创建两条(或更多)BGM 音轨:

  • village_bgm——村庄音乐,类型 BGM,循环开启
  • dungeon_bgm——地牢音乐,类型 BGM,循环开启

播放列表里放 village_bgm 作为默认曲目,自动播放开启。

第 2 步:创建变量

编辑器 → 变量 标签页 → 添加变量

字段填什么
显示名称当前地点
IDlocation
类型字符串
默认值village

第 3 步:创建行为

编辑器 → 行为 标签页 → 添加行为

行为名称: 前往地牢

触发条件: 动作 → 动作 ID 填 go-dungeon

执行动作(按顺序):

序号动作类型设置作用
1修改变量location 设为 dungeon记录玩家去了地牢
2播放音乐音轨 dungeon_bgm,操作:crossfade,渐变时长 2丝滑切歌
3启用知识条目地牢氛围打开地牢的世界观
4禁用知识条目村庄氛围关掉村庄的世界观

同样创建「返回村庄」行为,动作 ID go-village,执行反向操作(crossfade 到 village_bgm,开关条目反过来)。

第 4 步:在消息渲染器里触发

消息渲染器 的 TSX 代码中,按钮点击时调用 executeAction

tsx
<button onClick={() => api.executeAction("go-dungeon")}>
  前往地牢
</button>

行为会依次执行所有动作——改变量、切歌、开关条目,一键搞定。

什么是 crossfade? 交叉淡入淡出——旧曲目渐渐变小声的同时,新曲目渐渐变大声。两首曲子有一小段时间同时播放,听起来像电影场景切换,不会突然断掉。渐变时长建议 2-3 秒。


模式 3:关键词触发音效

你要做的

AI 写到"爆炸"时自动播放爆炸音效。玩家说"开门"时播放门打开的嘎吱声。不需要写行为,直接在 音频 标签页的条件 BGM 里就能配。

原理

条件 BGM 有一个触发方式叫 ai-keyword(AI 关键词)和 keyword(玩家关键词)。引擎会扫描每条消息的文字,匹配到关键词就播放对应的音轨。虽然功能名字叫"条件 BGM",但它可以指向任何类型的音轨——包括 SFX。

一步步来

第 1 步:创建 SFX 音轨

音频 标签页创建音效轨道:

爆炸音效:

字段填什么
显示名称爆炸
IDexplosion_sfx
类型SFX
循环关闭(音效通常只播一次)
音量0.9

开门音效:

字段填什么
显示名称开门声
IDdoor_open_sfx
类型SFX
循环关闭
音量0.8

第 2 步:创建条件 BGM 规则

同在 音频 标签页,找到「条件 BGM」区域 → 点击「添加规则」

规则 1:AI 说"爆炸"时播放音效

字段填什么为什么这样填
名称AI 爆炸音效给你自己看的
触发方式AI 关键词 (ai-keyword)当 AI 的回复里出现指定关键词时触发
关键词爆炸, 炸裂, 爆破可以填多个近义词,命中任一个就触发
目标音轨explosion_sfx播放爆炸音效
停止当前 BGM关闭音效是叠加在 BGM 上面的,不要停 BGM

规则 2:玩家说"开门"时播放音效

字段填什么为什么这样填
名称玩家开门音效给你自己看的
触发方式玩家关键词 (keyword)当玩家发送的消息里出现指定关键词时触发
关键词开门, 推门, 打开门多个近义词
目标音轨door_open_sfx播放开门音效
停止当前 BGM关闭同上

效果

AI 写道:「轰——!远处传来一声惊天动地的爆炸,火光照亮了整片天空。」
  → 引擎扫描到「爆炸」→ 自动播放 explosion_sfx
  → 玩家听到爆炸音效,同时 BGM 继续播放

玩家输入:「我走到门前,开门看看。」
  → 引擎扫描到「开门」→ 自动播放 door_open_sfx

SFX 和 BGM 的区别

SFX(音效)播一次就停。BGM(背景音乐)会循环或根据播放列表继续。当条件 BGM 规则指向一个 SFX 类型的音轨时,它只会播一次,不会替换正在播的背景音乐。但如果 stopPreviousBGM 设成了 true,它会先停掉当前 BGM 再播这个音轨——SFX 通常不需要这么做。


模式 4:条件 BGM——变量驱动自动切歌

你要做的

不用写行为,直接在 音频 标签页里配一条规则:当 hp 降到 20 以下时,自动切换到紧张的危机音乐;hp 回到 20 以上后,自动切回默认曲目。

原理

条件 BGM 的 variable 触发方式会在每次变量变化后自动检查。条件满足 → 切到目标曲目;条件不再满足 → 根据 fallback 设置回退(回到播放列表默认曲目,或回到之前那首)。

一步步来

第 1 步:准备音轨

确保 音频 标签页里有:

  • explore_bgm——默认探索音乐(在播放列表里)
  • crisis_bgm——危机音乐(只在条件触发时播放,不需要放进播放列表)

第 2 步:创建条件 BGM 规则

音频 标签页 → 条件 BGM → 添加规则

字段填什么为什么这样填
名称低血量危机音乐给你自己看的
触发方式变量 (variable)根据变量值来决定
条件hp < 20当 hp 小于 20 时触发
条件逻辑全部满足 (all)只有一个条件,allany 效果一样
目标音轨crisis_bgm切到危机音乐
优先级10如果有多条规则同时满足,优先级高的赢
淡入时长1新曲目渐渐响起
淡出时长1旧曲目渐渐消失
停止当前 BGM开启停掉探索曲再播危机曲
回退default条件不再满足时(hp 回到 20 以上),自动回到播放列表的默认曲目

效果

玩家探索中,BGM 是 explore_bgm
  → AI 回复:[hp: -15](hp 从 30 降到 15)
  → 引擎检测到 hp < 20,条件满足
  → explore_bgm 1 秒淡出,crisis_bgm 1 秒淡入
  → 气氛立刻紧张起来

玩家使用治疗药水
  → AI 回复:[hp: +20](hp 从 15 回到 35)
  → 引擎检测到 hp 不再 < 20,条件不满足
  → fallback: "default" → 自动回到 explore_bgm

多条件组合

你可以在一条规则里加多个条件。比如:hp < 20 并且 location == "dungeon" → 只有在地牢里低血才播危机音乐。条件逻辑选 all(全部满足)即可。


模式 5:环境音循环

你要做的

在场景背景里持续播放环境音——雨声、风声、酒馆嘈杂声——和 BGM 叠加在一起,增强沉浸感。

原理

Ambient(环境音)是第三种音轨类型。它独立于 BGM 播放——你可以同时播一首 BGM + 一段环境音。环境音通常设为循环、音量较低,作为持续的氛围底色。

一步步来

第 1 步:创建 Ambient 音轨

音频 标签页 → 添加音轨

字段填什么
显示名称雨声
IDrain_ambient
类型Ambient
循环开启
音量0.3(环境音要比 BGM 小声,作为底色)
淡入3 秒(渐渐出现,不突兀)
淡出3

可以多创建几个:wind_ambient(风声)、tavern_ambient(酒馆嘈杂声)、forest_ambient(森林鸟叫虫鸣)。

第 2 步:用条件 BGM 控制环境音

和模式 4 一样,用条件 BGM 规则来控制环境音的播放。

规则:在森林时播放森林环境音

字段填什么
名称森林环境音
触发方式变量 (variable)
条件location == forest
目标音轨forest_ambient
停止当前 BGM关闭
回退default

关键:stopPreviousBGM 必须关闭。 环境音是叠加在 BGM 上面的,不应该停掉 BGM。如果开了,切换环境音的时候会把正在播的背景音乐也停掉。

也可以用行为控制

如果你已经有了场景切换的行为(像模式 2 那样),直接在行为的动作列表里加一条「播放音乐」动作,目标是环境音轨即可:

序号动作类型设置作用
1修改变量location 设为 forest记录地点
2播放音乐forest_bgm,操作:crossfade,渐变 2 秒切换 BGM
3播放音乐forest_ambient,操作:play,淡入 3 秒叠加环境音
4播放音乐tavern_ambient,操作:stop,淡出 3 秒停掉旧环境音

这样一条行为同时完成了 BGM 切换 + 环境音更替。

环境音的音量建议

BGM 一般 0.5-0.7,环境音 0.2-0.4,SFX 0.7-1.0。这样三层声音叠在一起不会打架。


模式 6:从自定义组件控制音频

你要做的

在消息渲染器里做一个"点歌机"——几个按钮,点一个就播对应的音乐,点「停止」就停。这是纯 UI 控制,不需要写行为或条件规则。

原理

useYumina() 提供了两个音频 API:

  • api.playAudio?.(trackId, opts) — 播放指定音轨
  • api.stopAudio?.(trackId?) — 停止指定音轨(不传 ID 则停止全部)

这两个方法可以在消息渲染器的 TSX 代码里直接调用。

一步步来

第 1 步:准备音轨

确保 音频 标签页里已经注册了你想播的音轨(像模式 1 那样创建)。假设你有:

  • jazz_bgm — 爵士乐
  • rock_bgm — 摇滚
  • classical_bgm — 古典

第 2 步:写消息渲染器代码

编辑器 → 消息渲染器 标签页 → 在渲染器代码里加入点歌机 UI:

tsx
export default function Renderer({ content, renderMarkdown, messageIndex }) {
  const api = useYumina();
  const msgs = api.messages || [];
  const isLastMsg = messageIndex === msgs.length - 1;

  const tracks = [
    { id: "jazz_bgm", label: "爵士乐", color: "#7c3aed" },
    { id: "rock_bgm", label: "摇滚", color: "#dc2626" },
    { id: "classical_bgm", label: "古典", color: "#0891b2" },
  ];

  return (
    <div>
      <div
        style={{ color: "#e2e8f0", lineHeight: 1.7 }}
        dangerouslySetInnerHTML={{ __html: renderMarkdown(content) }}
      />

      {isLastMsg && (
        <div style={{
          marginTop: "12px",
          padding: "12px",
          background: "rgba(30,41,59,0.5)",
          borderRadius: "8px",
          border: "1px solid #334155",
        }}>
          <div style={{ fontSize: "12px", color: "#94a3b8", marginBottom: "8px" }}>
            点歌机
          </div>
          <div style={{ display: "flex", gap: "8px", flexWrap: "wrap" }}>
            {tracks.map((t) => (
              <button
                key={t.id}
                onClick={() => api.playAudio?.(t.id, { fadeDuration: 1.5 })}
                style={{
                  padding: "8px 16px",
                  background: t.color,
                  border: "none",
                  borderRadius: "6px",
                  color: "#fff",
                  fontSize: "13px",
                  cursor: "pointer",
                }}
              >
                {t.label}
              </button>
            ))}
            <button
              onClick={() => api.stopAudio?.()}
              style={{
                padding: "8px 16px",
                background: "#475569",
                border: "none",
                borderRadius: "6px",
                color: "#e2e8f0",
                fontSize: "13px",
                cursor: "pointer",
              }}
            >
              停止
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

代码逐行解释:

  • api.playAudio?.(t.id, { fadeDuration: 1.5 }) — 播放指定音轨,带 1.5 秒淡入。如果当前有其他曲子在播,会自动停掉再播新的
  • api.stopAudio?.() — 不传参数 = 停止所有正在播放的音频
  • isLastMsg — 只在最后一条消息上显示点歌机,避免每条消息都重复

更高级的用法

你可以读取变量来控制 UI 状态。比如用一个变量 now_playing 记录当前曲目 ID,然后在按钮上显示"正在播放"的标记:

tsx
const nowPlaying = String(api.variables.now_playing || "");

// 在按钮点击里同时更新变量
onClick={() => {
  api.playAudio?.(t.id, { fadeDuration: 1.5 });
  api.setVariable("now_playing", t.id);
}}

// 按钮上显示状态
{nowPlaying === t.id ? "♪ " + t.label : t.label}

模式 7:AI 驱动的音频控制

你要做的

让 AI 在叙述过程中自然地控制音乐——描写进入酒馆时播放欢快的手风琴曲,描写战斗打响时切到激昂的战斗 BGM,描写角色受伤时播放疼痛音效。

原理

AI 可以在回复中嵌入 [audio: trackId action] 格式的指令。引擎会自动识别并执行这些指令,同时把它们从玩家看到的文字中剥离掉——就像电影剧本里的舞台指示,观众看不到,但幕后工作人员会照着执行。

一步步来

第 1 步:注册所有可能用到的音轨

音频 标签页把你想让 AI 控制的音轨全部创建好:

  • tavern_bgm — 酒馆曲
  • battle_bgm — 战斗曲
  • sword_clash_sfx — 刀剑碰撞音效
  • pain_sfx — 受伤音效
  • rain_ambient — 雨声

第 2 步:在系统提示词里告诉 AI 有哪些音轨

AI 不会自动知道你注册了哪些音轨。你需要在 知识库 标签页创建一个条目,列出可用的音轨和使用规则:

条目名称: 音频指令参考

区域: 预设

内容:

[Audio Control System]
你可以在回复中使用以下音频指令来控制音乐和音效。指令会被自动执行并从玩家可见文字中移除。

可用指令格式:
- [audio: trackId play] — 播放
- [audio: trackId play 2.0] — 播放,带 2 秒淡入
- [audio: trackId stop] — 停止
- [audio: trackId stop 1.5] — 停止,带 1.5 秒淡出
- [audio: trackId crossfade 2.0] — 交叉淡入淡出切换,过渡 2 秒
- [audio: trackId volume 0.5] — 调节音量到 0.5
- [audio: trackId play chain:nextTrackId] — 播完后自动衔接下一首

可用音轨:
- tavern_bgm — 酒馆欢快手风琴曲(适合社交、购物场景)
- battle_bgm — 激昂战斗曲(适合战斗、追逐场景)
- sword_clash_sfx — 刀剑碰撞音效(适合近战动作描写)
- pain_sfx — 受伤音效(适合角色受伤时)
- rain_ambient — 雨声环境音(适合雨天场景)

使用原则:
- 在合适的叙述节点自然地插入音频指令
- 场景转换时用 crossfade 切歌,过渡时长 1.5-2.5 秒
- 音效配合动作描写,放在对应的动作文字旁边
- 不要过度使用——每段回复最多 2-3 条音频指令

第 3 步:AI 的回复示例

告诉 AI 这些规则后,它的回复可能长这样:

你推开酒馆的木门,一股温暖的空气扑面而来。[audio: tavern_bgm crossfade 2.0]

酒馆里热闹非凡——角落里有人在弹手风琴,吧台前的矮人正在大声猜拳。你刚找了个座位坐下,一个蒙面人突然拔刀朝你劈来!

[audio: battle_bgm crossfade 0.5] [audio: sword_clash_sfx play]

你本能地翻身躲开,桌子被劈成两半。

玩家看到的是干净的叙述文字,同时听到:酒馆曲渐入 → 突然切战斗曲 + 刀剑碰撞音效。

chain 指令的特殊用法

chain 可以让一个音轨播完后自动衔接另一个:

号角声在山谷间回荡,战争即将开始![audio: war_horn_sfx play chain:battle_bgm]

war_horn_sfx 这段号角音效播完后,battle_bgm 会自动开始——先放前奏再接主曲,比直接切歌更有仪式感。

AI 可能忘记使用指令

AI 不总是记得插入音频指令,尤其是在长对话中。对于关键场景的 BGM 切换(比如进入战斗区域),建议同时设置条件 BGM 规则(模式 4)作为保底。AI 指令是锦上添花,条件 BGM 是安全网。


综合速查表

音轨类型

类型用途通常设置
BGM背景音乐循环开启,音量 0.5-0.7
SFX一次性音效循环关闭,音量 0.7-1.0
Ambient环境音循环循环开启,音量 0.2-0.4

控制音频的 5 种方法

你想做的事用哪种方式在哪里设置
进入世界自动播放 BGM播放列表 + 自动播放音频 标签页 → BGM 播放列表
变量满足条件时自动切歌条件 BGM(variable 触发)音频 标签页 → 条件 BGM
AI 回复出现关键词时播音效条件 BGM(ai-keyword 触发)音频 标签页 → 条件 BGM
玩家消息出现关键词时播音效条件 BGM(keyword 触发)音频 标签页 → 条件 BGM
到指定回合数时切歌条件 BGM(turn-count 触发)音频 标签页 → 条件 BGM
场景切换时交叉淡入淡出行为 + 播放音乐动作行为 标签页
按钮点击播放/停止消息渲染器 api.playAudio?.() / api.stopAudio?.()消息渲染器 标签页
AI 在叙述中触发AI 音频指令 [audio: trackId action]知识库 标签页(告诉 AI 规则)

AI 音频指令速查

指令效果
[audio: trackId play]播放
[audio: trackId play 2.0]播放,2 秒淡入
[audio: trackId stop]停止
[audio: trackId stop 1.5]停止,1.5 秒淡出
[audio: trackId crossfade 2.0]交叉淡入淡出,过渡 2 秒
[audio: trackId volume 0.5]调节音量
[audio: trackId play chain:nextId]播完后自动衔接下一首

条件 BGM 触发方式

触发方式什么时候触发典型用途
variable变量满足条件时hp < 20 播危机曲
ai-keywordAI 回复含关键词时AI 写"爆炸"播爆炸音效
keyword玩家消息含关键词时玩家说"演奏"播音乐
turn-count到达指定回合时第 10 回合播倒计时曲
session-start会话开始时固定的开场曲

行为 play-audio 动作参数

参数说明
音轨 ID (trackId)对应音频标签页里注册的音轨 ID
操作 (action)play(播放)、stop(停止)、crossfade(渐变切换)、volume(调音量)
音量 (volume)0-1,可选
渐变时长 (fadeDuration)秒,可选,crossfade 时建议 1.5-3 秒

消息渲染器音频 API

方法说明
api.playAudio?.(trackId, opts)播放音轨。opts 可以包含 fadeDuration
api.stopAudio?.(trackId?)停止音轨。不传 ID 则停止全部

常见问题

现象可能的原因解决方法
听不到声音浏览器禁止自动播放现代浏览器要求用户先和页面有交互(点击、打字)才允许播放音频。让玩家先发一条消息,或在播放列表里把「等待首条消息」打开
BGM 切换时有断裂感没用 crossfade确认行为的「播放音乐」操作选的是 crossfade,渐变时长至少 1.5 秒
音效和 BGM 互相打断stopPreviousBGM 设成了 trueSFX 类型的条件 BGM 规则要把「停止当前 BGM」关掉
AI 不使用音频指令知识条目里没告诉 AI创建一个预设条目,列出所有可用的音轨 ID 和指令格式(见模式 7)
环境音太吵音量太高环境音建议 0.2-0.4,和 BGM 的 0.5-0.7 拉开层次
条件 BGM 没触发变量值类型不匹配确认条件里的值类型和变量类型一致(比如数字变量要用数字比较,不要写成字符串)
多条规则冲突优先级相同给不同的条件 BGM 规则设不同的优先级,数字越大越优先

这是实战配方 #14:音效设计指南

音频系统的设计哲学是:简单的事情一步到位(播放列表 + 自动播放),复杂的事情分层解锁(条件 BGM → 行为控制 → AI 指令 → 自定义 API)。你不需要一次学完所有模式——从模式 1 开始,等需要更多控制时再往后看。