Template_No.1:直接看最简操作教程。本文操作步骤默认以 Desktop 桌面版为主:
.pulse 文件;.pulse 文件。Builder 现在把设计师工具分成两个作者专用区域,试听者和购买者不会看到这些表单:
它们不是一套必须从头填到尾的表格:
如果你正在使用 Template_No.1,最安全的做法是:
volume 参数,不增不删;| Builder 区域 | 会不会改变声音 | 是否需要游戏程序配合 | Template_No.1 建议 |
|---|---|---|---|
| 分层音轨 | 会;进入状态时会多播放声音 | 固定播放不需要代码,但当前 SDK 不能动态调层音量 | 保持空白 |
| 游戏参数 | 选了声音目标后,默认值或新数值都会生效 | 连续变化通常需要游戏代码;状态预设也可以覆盖 | 保留现有 volume,不要新增 |
| 游戏接入合同 | 不会 | 决定开发者可以调用什么 | 交付前主动确认 |
| 项目元数据 / 导出信息 | 不会 | 不需要 | 商业交付前填写 |
| 技术标识 | 不改变声音,但会影响游戏识别 | 接入时会使用 | 不确定就保持原样 |
你只是想试听、修改状态或导出 Template_No.1 吗?
├─ 是
│ └─ 不需要添加分层音轨,也不要改游戏参数。
│ 如果要对外交付,再检查「交付与游戏接入」。
│
└─ 不是
│
├─ 你有单独导出的鼓、贝斯、氛围等同步分轨吗?
│ ├─ 有 → 可以考虑「分层音轨」
│ └─ 没有 → 不要添加 Layer
│
├─ 游戏需要在不切换状态的情况下连续改变声音吗?
│ 例如危险度从 0% 慢慢升到 100%
│ ├─ 需要 → 可以定义「游戏参数」
│ └─ 不需要 → 只使用状态切换
│
├─ 这个包要交给别人、上传或出售吗?
│ ├─ 是 → 确认游戏接入合同,再填写标题、描述、授权和标签
│ └─ 否 → 导出信息可以暂时不改
│
└─ 这是全新的独立产品,而不是原包的更新吗?
├─ 是 → 在接入前建立一次新的模块 ID 和 Slug
└─ 否 → 不要修改技术标识
表单里改完内容,不代表磁盘上的 .pulse 已经更新。
| 区域 | 什么时候提交到当前工程 | 之后还要做什么 |
|---|---|---|
| 分层音轨 | 添加、勾选片段、改默认音量和删除会立即提交;改名称要按 Enter 或移开焦点 | Desktop 保存/另存为;Web 导出 |
| 游戏参数 | 必须点击「保存参数」;点「取消」会丢弃表单草稿 | Desktop 保存/另存为;Web 导出 |
| 游戏接入合同 | 必须点击「保存接入合同」;未点击时只是勾选草稿 | Desktop 保存/另存为;Web 导出 |
| 导出信息 | 必须点击「保存导出信息」;没点时只是未提交草稿 | Desktop 保存/另存为;Web 导出 |
最简单的记法:
第一层:把当前表单提交给工程
第二层:把整个工程写成 .pulse 文件
| 名称 | 外行解释 | 例子 |
|---|---|---|
| 音频素材(Resource) | 导入的原始音频文件 | intro.wav |
| 片段(Segment) | 从素材中划出的可播放部分 | intro.wav 的第 0–21.6 秒 |
| 状态(State) | 游戏当前处于哪种音乐场景 | 探索、战斗、胜利 |
| 主音乐 | 进入状态后主要播放的片段 | 进入「战斗」后播放战斗循环 |
| 分层音轨(Layer) | 跟主音乐同时播放的额外分轨 | 额外鼓组、贝斯、氛围 |
| 游戏参数 | 游戏程序可以连续调节的虚拟旋钮 | 危险度、总音量、音色明暗 |
| 游戏接入合同 | 设计师主动公开给开发者的状态和参数清单 | 公开探索、战斗和紧张度 |
| 内部内容 | 包中存在、但游戏开发者不应调用的实现细节 | 过渡用状态、调试参数、素材和 Layer |
| 导出信息 | 写进 .pulse 包里的展示与授权信息 | 标题、描述、买家使用授权、标签 |
| 技术标识 | 系统和游戏用来认包的稳定编号 | minimal-tech-pilot |
可以把一个 .pulse 理解成:
音频素材
↓ 切成可播放片段
状态及转场
↓ 可选:分层音轨、游戏参数
游戏接入合同
↓
项目元数据与授权
↓
一个可播放、可接入、可交付的 .pulse 文件
分层音轨是在某个状态的主音乐已经播放时,再让另一段独立声音一起播放。
例如:
战斗状态
├─ 主音乐:基础战斗循环
├─ Layer:独立鼓组
└─ Layer:独立高强度旋律
进入战斗状态时,三段声音会同时开始。离开战斗状态时,这些 Layer 也会停止。
只有下面条件都满足时才考虑添加:
如果拿到的是已经混好的 intro.wav、verse.wav、combat.wav,就不要使用 Layer。
| 界面项 | 实际作用 |
|---|---|
intro 的音轨 | 表示你正在编辑 intro 状态的额外分层,不影响其他状态 |
+ 添加音轨 | 给当前状态增加一个 Layer,不负责上传新音频 |
| 音轨名称 | 给人看的名字,例如「鼓组」或「环境氛围」;按 Enter 或移开输入焦点后才提交 |
| 片段 | 从已经导入的片段中选择这个 Layer 要播放的内容 |
| 音量 | 下次进入该状态时使用的初始音量,不是当前正在响的实时推子 |
| 删除 | 删除 Layer 定义,不会删除原始音频素材 |
combat-drums.wav。.pulse。这些不是使用技巧,而是当前代码的真实边界。
每个 Layer 目前只会播放所选列表中的第一个片段。
界面虽然允许勾选多个,但后面的片段不会轮播。当前请坚持「一层一个片段」。
生产上只建议使用循环 Layer。
非循环 Layer 播完后的生命周期还不适合作为一次性音效使用。
公共游戏 SDK 目前不能实时调整 Layer 音量。
游戏进入状态后会使用制作时设定的默认音量,但不能通过当前 PulseGameRuntime 动态推高鼓组。
游戏参数不能控制单独某个 Layer。
参数作用于整条总输出,不会自动映射到某一层的音量。
Layer 自身没有独立的交叉淡入淡出。
立即切换时,即使主音乐在交叉淡化,旧 Layer 仍会直接停止、新 Layer 直接开始;「同步切」时 Layer 也会从自己的起点开始,不会跟随主音乐的当前位置。素材必须从同一拍点导出,优先使用「下小节切」转场。
Layer 不是 Stinger。
当前产品还没有真正的 Stinger/一次性叠加触发能力。
刚改完 Layer 时,当前正在响的声音不一定立刻更新。
Layer 的片段和默认音量是下次启动该状态时使用的定义。请停止重播,或离开后重新进入状态再判断结果。
Template_No.1 应该怎样处理Template_No.1 的 intro、verse、build up、bridge、outro 是完整混音,不是同步 Stem(独立分轨)。
因此:
分层音轨保持空白,不要为了「填满高级声音设置」而添加内容。
游戏参数是游戏程序能够实时转动的虚拟旋钮。
例如,游戏可以不断把危险度传给音乐:
危险度 0 → 音色较暗
危险度 50 → 音色开始变亮
危险度 100 → 音色最明亮、最紧张
它和状态切换不同:
| 状态 | 参数 |
|---|---|
| 在几个明确场景之间切换 | 在一个范围内连续变化 |
| 例如探索 → 战斗 | 例如危险度 0 → 100 |
| 通常会换主音乐 | 可以只改变音量、明暗或空间感 |
定义一个 tension 参数后,它不会:
参数的默认值会在播放初始化时使用,状态预设或状态效果器也可能覆盖它。如果希望参数跟随玩家血量、敌人数量等玩法数据连续变化,游戏开发者仍然必须主动调用这个参数,并传入合法数值。
| 字段 | 外行解释 | 示例 |
|---|---|---|
| 游戏调用名称 | 必填;程序使用的固定名字,首次保存后界面不能再改 | tension |
| 英文名称 | 必填;英文界面展示名称 | Tension |
| 中文名称 | 中文界面展示名称 | 紧张度 |
| 最小值 | 旋钮最小允许值 | 0 |
| 最大值 | 旋钮最大允许值 | 100 |
| 步长 | 界面每次最小变化多少 | 1 |
| 默认值 | 初始化时先使用什么;当前状态预设或效果器可能覆盖它 | 20 |
| 单位 | 只用于展示 | %、Hz、s、dB |
| 控制内容 | 这个旋钮最终改变什么声音 | 总音量、音色明暗 |
| 自定义 DSP 范围 | 把好理解的输入值翻译成音频引擎需要的值 | 0–100 翻译成 0–1 |
| 选项 | 外行解释 | 使用提醒 |
|---|---|---|
| 仅传递游戏数据 | 记录数值并产生事件,但不会直接改变声音 | 不要期待它产生听觉变化 |
| 总音量 | 整个音乐包一起变大声或变小声 | 引擎实际需要 0–1 |
| 音色明暗 | 低值更闷、更暗;高值更开、更亮 | 实际单位是 Hz |
| 滤波共振 | 强调滤波点附近的声音 | 容易尖锐,外行不建议使用 |
| 混响量 | 房间感、空间感的多少 | 引擎实际需要 0–1 |
| 延迟时间 | 每次回声之间隔多久 | 引擎使用秒,最大会限制到 5 秒 |
| 延迟反馈 | 回声重复和衰减的程度 | 不要设置到 1;引擎上限约为 0.95 |
| 压缩强度 | 界面这样命名,但代码实际控制「压缩阈值」 | 实际是 -100 dB 至 0 dB;数值越低,通常越多声音进入压缩,不懂时不要改 |
最简单的比喻是「翻译表」。
游戏和界面喜欢使用容易理解的范围:
0% → 50% → 100%
但音频引擎可能需要:
0.0 → 0.5 → 1.0
于是可以设置:
参数范围:0–100
DSP 范围:0–1
再举一个音色明暗的例子:
参数范围:0–100
DSP 范围:900–6200 Hz
游戏只需要理解「危险度 70」,引擎会把它换算成对应的滤波频率。
tension、player_health。.pulse 文件。参数首次保存后,当前界面不能直接修改游戏调用名称。如果名称写错,只能在尚未接入时删除后重建;接入开始后不要改名。
默认不要为了「让高级声音设置看起来完整」而添加参数。只有游戏已经决定怎样计算和传入紧张度时,才参考下面的模板。
如果游戏确实需要一个连续的「紧张度」旋钮,可以从下面开始:
游戏调用名称:tension
英文名称:Tension
中文名称:紧张度
最小值:0
最大值:100
步长:1
默认值:20
单位:%
控制内容:音色明暗
自定义 DSP 范围:900–6200
但在真实游戏代码决定怎样计算 tension 之前,不要仅仅为了展示而添加它。
NaN 和无穷值会立即报错,因此拼写和数值都必须正确。Template_No.1 的现有 volume 参数当前模板已经有一个可工作的总音量参数:
游戏调用名称:volume
范围:0–100
步长:1
默认值:80
单位:%
控制内容:总音量
DSP 范围:0–1
人话解释:界面显示 50%,引擎实际收到 0.5。
如果你还没有明确的新接入需求,保留它,不要增删。
游戏接入合同是一张由 Pulse 设计师确认的「开发者可调用清单」。
一个包里可能有很多为了编排而存在的状态和参数,但游戏开发者通常只需要很少几个稳定入口。例如:
包内实际内容
├─ exploration 公开:游戏可调用
├─ combat 公开:游戏可调用
├─ combat-tail 内部:只用于音乐编排
├─ tension 公开:游戏可调用
└─ debug-filter 内部:只用于制作试听
过去开发者只能看到一长串 ID,再猜哪些该用。接入合同把这件事变成设计师的一次明确选择:勾选的才是公开 API,没勾选的都属于包内实现。
pulseContract、参数范围和最小接入代码;它不会改变声音,也不会替你设计游戏事件。游戏里的 encounter:start、boss:defeated 等事件名仍由游戏项目决定;合同只说明这些事件最终可以调用哪些 Pulse state/parameter ID。
在「交付与游戏接入」中打开「游戏接入合同」,会看到:
| 界面区域 | 怎样选择 |
|---|---|
| 游戏可调用状态 | 只勾选游戏业务需要主动切换的音乐状态 |
| 初始状态 | 模块列表中的第一个状态;一定公开,不能取消勾选 |
| 游戏可调用参数 | 只勾选开发者需要实时传值的参数;可以一个都不选 |
| 已选择摘要 | 显示最终公开的状态和参数数量 |
| 保存接入合同 | 把当前选择写进工程的 package metadata |
素材、片段和 Layer 不会出现在合同选择里,因为它们永远是包内实现。
runtime 加载后必须有一个确定的起点。当前 v0.1 把模块列表中的第一个状态当作初始状态,因此它必须包含在公开状态中,界面会固定勾选。
如果第一个状态不适合作为游戏起点,应先回到状态编排,调整模块本身的第一个状态,而不是试图在合同里隐藏它。合同至少会有这一个公开状态;公开参数则可以为空。
旧版 .pulse 没有接入合同。打开这种包时,界面会显示警告,并把当前全部状态和参数先勾上,作为一个待确认的起点。
这不表示「全部公开」已经是正确答案。请逐项检查:
为了兼容旧文件,只是打开或普通保存旧包时,系统不会偷偷把推断结果写成正式合同。必须由设计师主动点击「保存接入合同」,这份选择才算得到确认。
这种「默认不公开」的行为是为了避免一次内部编辑意外扩大游戏 API。
pulseContract 和接入示例。.pulse 与生成的合同一起交给开发者。metadata.publicInterfaceBuilder 会把确认结果写成下面的 metadata:
{
"publicInterface": {
"schemaVersion": 1,
"initialStateId": "exploration",
"stateIds": ["exploration", "combat"],
"parameterIds": ["tension"]
}
}
规则是:
schemaVersion 当前固定为 1;initialStateId 必须是模块第一个状态,并且也必须出现在 stateIds;stateIds 和 parameterIds 不能重复,也不能引用已经不存在的内容;parameterIds 可以是空数组;Template_No.1 应该怎样选择不要因为界面最初全部勾选,就直接把五个状态和 volume 全部公开。
intro、verse、build up、bridge、outro 对应状态,逐个问:「游戏是否真的需要主动切到这里?」需要才勾选。volume;如果游戏使用自己统一的音量系统,可以不公开它。这里没有一份适合所有游戏的固定答案。合同表达的是这个具体商品的游戏用法,应由内容设计和接入需求共同决定。
导出信息不负责播放音乐,只负责告诉别人这个
.pulse包叫什么、是什么、允许怎样使用。
| 字段 | 作用 | 是否影响声音 |
|---|---|---|
| 英文标题 | 英文预览页、商品页或文件展示名称;当前为必填 | 否 |
| 中文标题 | 中文界面展示名称 | 否 |
| 英文描述 | 向英文用户说明这个包能做什么 | 否 |
| 中文描述 | 向中文用户说明这个包能做什么 | 否 |
| 买家使用授权 | 记录真实合同授予买家的使用权 | 否 |
| 标签 | 写进包里,供外部或未来的目录系统分类;当前 Builder 本身不提供标签搜索 | 否 |
| 技术标识 | 让系统和游戏稳定识别同一个产品 | 不影响声音,但影响接入 |
如果项目会在中文界面展示,建议同时填写中文标题和中文描述。当前留空可能保存成空字符串,而不是自动回退到英文。
在输入框里写下授权文字,不会自动产生版权,也不会替代合同。它只是把已经真实存在的授权记录进包里。
这里必须先分清两个不同问题:
.pulse 的人被允许怎样使用、能否继续转售或再分发。当前已经确认的是第一项:项目方对 Template_No.1 音乐拥有商业使用和再分发权。这份来源记录保存在仓库的 ASSETS_LICENSE.md。
「买家使用授权」输入框用于填写随 .pulse 交付给最终用户的许可摘要。除非合同明确允许最终用户继续再分发,否则不要直接复制一句没有主语的「redistribution authorized」,以免把项目方拥有的权利误写成买家拥有的权利。
如果真实合同包含地域、平台、项目数量、二次编辑或转售限制,应使用合同中的准确文字,不要自行扩大权利范围。拿不准时,先保留内部权利记录,再让实际授权条款确定这个字段的最终文案。
使用英文逗号或换行分隔:
interactive-music, game, technology
系统会去掉首尾空格和重复标签。中文顿号 、 不会被当作分隔符。
这是最容易误解的地方:
.pulse。.pulse 文件。可以记成:
保存导出信息 = 把标签贴到当前工程
Desktop 保存 / 另存为 = 把整个工程真正写进 .pulse 文件
Web 导出 = 生成 .pulse 文件
这个区域不向普通用户暴露兼容字段。已有包的兼容声明会被保留;当包已有兼容声明时,Builder 会根据工程内容自动提升能直接判定的 required features,包括状态转场、下小节 / 片段结束 / 同时间点转场、Layer、参数映射和 DSP 参数。
完全新建的项目会在第一次保存导出信息、保存接入合同、保存到 Web 本地工程或直接导出时自动带上 Builder 的默认兼容声明;以后检测到实际使用的能力时,还会提升对应的 required features。导入的旧包则保持原声明不变,即使它原本没有 compatibility,也不会仅因打开或编辑标题而被 Builder 静默补成一整套默认值;如果新增公开接入合同,系统仍会写入该契约要求的最低 runtime 版本。正式交付测试仍应检查目标 runtime 版本与实际用到的 required features,但不需要设计师手工维护隐藏字段。
| 字段 | 外行理解 |
|---|---|
| 模块 ID | 系统内部识别这个包的稳定编号 |
| Slug | 适合文件名、链接或目录使用的稳定英文名称 |
当前 Builder 会在它们留空时,根据英文标题自动生成。自动生成后不要反复修改。
当前界面还没有完整校验 ID/Slug 的安全字符。手动填写时只使用小写英文字母、数字和短横线,例如 minimal-tech-pilot;不要使用空格、中文、斜杠或特殊符号。
只有一种安全情况:
你正在创建一个全新的独立产品,并且游戏开发者还没有开始接入。
例如,从内置模板制作一个新的对外商品时,可以先「另存为」,然后一次性设置:
模块 ID:minimal-tech-pilot
Slug:minimal-tech-pilot
之后无论修改标题、描述、音频还是版本,都保持这两个值不变。
不确定时,答案永远是:保持原样。
Template_No.1 最简操作教程Template_No.1。intro、verse、build up、bridge、outro。volume 参数。.pulse。.pulsevolume 参数。 不随意删除或修改调用名称。volume。Minimal Tech极简科技interactive-music, game, technology.pulse。pulseContract,再完成交付检查。pulseContract 没有合同警告,参数范围正确.pulse 被用于预览(Preview)、测试和游戏接入Layer = 跟某个状态一起播放的附加循环分轨
参数 = 带默认值、也可以由状态或游戏实时改变的全局声音旋钮
Stinger = 事件发生时覆盖在当前音乐上的一次性短句
当前版本:
trigger() 当前只是状态切换的别名,不能当作通用音效触发器。不要用非循环 Layer 假装 Stinger,也不要把一个完整状态误当成不会打断主音乐的叠加音效。
不需要。「高级声音设置」是可选的;但准备交给开发者时,应在「交付与游戏接入」里主动确认一次接入合同和项目元数据。
不是。那只是兼容旧包的待确认起点。取消勾选游戏不需要调用的内部状态和参数,再点击「保存接入合同」。
会。接入合同不删除内容,也不改变包内转场和播放编排;它只阻止游戏代码把内部 ID 当成公开 API 直接调用。
当前模块的第一个状态就是 runtime 的确定起点,因此必须公开。如果起点选错,应先调整状态编排,而不是在合同中隐藏它。
可以。很多游戏只需要切换音乐状态,不需要连续参数。公开参数清单可以为空。
这是有意的安全行为。新内容默认是内部实现;只有设计师再次勾选并保存,才会扩大公开合同。
不是。主音乐应在状态的片段配置中设置。Layer 只负责额外叠加。
不会。当前只播放第一个,而且两段完整混音也不适合叠加。
不会。游戏代码必须自己计算危险度并调用 setGameParameter()。
不会。它只保存数值和产生事件。
不一定。混响实际需要 0–1,应设置 DSP 范围进行换算。
因为当前 DSP 参数作用于总输出,不是某个单独状态或 Layer。
某个状态预设或效果器可能仍然引用旧参数。恢复该参数,或清理所有引用后再导出。
因为还没有执行最终文件操作:Desktop 使用「保存 / 另存为」,Web 使用「导出」。
不会。它只是文字记录,既不会创造授权,也不会自动证明授权;最终应以真实合同和权利文件为准。
不要。标题可以改变,技术标识应保持稳定。
| 你想做什么 | 应该用什么 | 不要用什么 |
|---|---|---|
| 探索音乐切换到战斗音乐 | 状态与转场 | Layer、Stinger |
| 主音乐上持续加一层同步鼓组 | Layer | 两首完整混音 |
| 危险度连续改变整包音色明暗 | 游戏参数 | 新建几十个状态 |
| 决定开发者能切换哪些音乐状态 | 游戏接入合同 | 把包内所有 ID 发给开发者 |
| 保留过渡或调试状态但不让游戏调用 | 不在接入合同中勾选 | 删除仍被内部编排需要的内容 |
| 击杀时叠加一次短促乐句 | 当前版本暂不支持真正 Stinger | 非循环 Layer、trigger() |
| 修改商品名称和介绍 | 导出信息 | 技术标识 |
| 发布同一产品的新版本 | 保持原 ID/Slug | 新建技术标识 |
| 创建完全独立的新商品 | 接入前设置一次新 ID/Slug | 发布后反复修改 |
使用完整混音的 Template_No.1 | 状态切换 + 保留 volume 定义;是否公开按游戏需求 | 添加 Layer |
| 词 | 人话解释 |
|---|---|
| BPM | 音乐速度,例如 120 BPM 表示每分钟 120 拍 |
| Stem | 单独导出的鼓、贝斯、旋律、氛围等分轨,不是完整混音 |
| DSP | 声音处理,例如滤波、混响、延迟和压缩 |
| SDK | 给游戏开发者调用的一组现成程序接口 |
| Runtime | 游戏运行时真正负责加载和播放 .pulse 的部分 |
| AudioCore | Pulse 内部的底层音频引擎;普通用户无需直接操作 |
| Preview | 不接入游戏,直接试听包中状态变化的预览界面 |
公开合同 / pulseContract | 从 .pulse 的接入合同生成、供游戏代码复制使用的状态与参数清单 |
| Allowlist | 「只有列出来的才允许」;接入合同使用的公开清单规则 |
| 削波 | 音量过大导致波形顶住上限,听起来可能失真、爆裂 |