关于 audio-design
面向游戏开发者的通用音频设计技能,聚焦混音路由与自适应音乐。涵盖总线混音、侧链闪避、音效变化和节拍同步,不限定具体引擎 API。
主要功能
- 01总线路由与分贝音量控制
- 02为竞争音频进行侧链闪避
- 03自适应音乐分层与转场
- 04音效音高及采样变化
- 05节拍同步事件
适用场景
- 01按总线平衡音乐、音效、环境声和语音
- 02对话或关键音效播放时降低音乐
- 03根据战斗强度改变音乐
- 04变化重复音效并让事件与节拍同步
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill audio-design安装后在 Claude Code 中输入/audio-design确认已加载。
附带文件references/adaptive-music.md
详细介绍
音频设计
游戏音频由混音图和音乐系统构成。将所有声音路由到少量总线,以便平衡音量并处理声音组;通过分层和重新编排让音乐对游戏过程产生响应,而不是循环播放单条音轨。本技能介绍可移植的实践方法;如需具体 API,请将其用于 godot-audio、Unity 的 AudioMixer 或中间件(FMOD/Wwise)。
适用场景
- 用于设计总线/混音器布局、设置组音量,以及为声音组添加效果(混响、压缩、均衡)。
- 用于通过侧链在对话或冲击音效播放时降低音乐/环境音的音量。
- 用于构建可根据战斗/探索强度做出响应的自适应音乐。
- 用于添加音效变化(音高/采样随机化),以及让事件与节拍同步。
**不适用场景:**如需使用引擎特有的音频节点/流,请使用 godot-audio 或引擎的音频技能。加载/流式传输和资源导入属于引擎相关事项。如需控制总线音量的 UI 滑块,请参阅引擎的 UI 技能。
核心工作流
- **规划总线,而不是逐个声音设置音量。**典型结构:
Master ← {Music, SFX, Ambience, UI, Voice}。所有声音都通过总线播放;玩家的设置滑块映射到总线音量。不要手动设置数百个音频片段的音量。 - **使用分贝,而不是线性值。**感知到的响度呈对数关系。音量控件和自动化应以 dB 为单位;仅在边界处进行转换。
- **留出余量。**混音时让 Master 峰值低于 0 dBFS(设定目标响度,例如许多游戏可设为约 -14 至 -16 LUFS),以避免削波。
- **用侧链压缩器(或音量自动化)降低竞争声源的音量:**语音/重要音效播放时,音乐总线音量下降,随后恢复。
- **通过垂直分层(淡入/淡出各音轨)和/或水平重新编排(在音乐边界处切换片段)让音乐具备自适应能力。**参见参考资料。
- **通过小幅随机调整音高/音量和使用采样池,让重复音效有所变化,**避免脚步声和打击声听起来像机器播放。
- **在真实输出设备上确认效果。**使用耳机和扬声器监听;检查混音是否平衡、音量衰减是否明显但不会产生抽吸感、音乐转场是否落在节拍上——不要只凭编辑器的电平表来判断。
模式
1. 总线路由和 dB 增益
# Route sounds to named buses; control GROUPS, not individual clips.
sfx_player.bus = "SFX"
music_player.bus = "Music"
# Map a 0..1 settings slider to decibels (linear_to_db), the perceptual unit.
func set_bus_volume(bus_name: String, slider01: float) -> void:
var idx := AudioServer.get_bus_index(bus_name)
var db := linear_to_db(clamp(slider01, 0.0001, 1.0)) # 0 -> silence, 1 -> 0 dB
AudioServer.set_bus_volume_db(idx, db)
# RIGHT: slider -> dB via linear_to_db. WRONG: assigning slider01 straight as dB
# (a "0.5" would be only +0.5 dB — almost no change — and 0 would be 0 dB, full).
2. 通过侧链进行音量衰减(音乐在语音播放时降低)
# A compressor on the MUSIC bus, keyed by the VOICE bus, lowers music while
# dialogue plays, then releases. This is "sidechain ducking".
# Setup (engine-specific): add a compressor effect to the Music bus and set its
# sidechain to the Voice bus. Then tune:
# threshold: level on Voice that triggers ducking (e.g. -30 dB)
# ratio: how hard to duck (e.g. 8:1 for a clear dip)
# attack: fast (~10 ms) so music gets out of the way promptly
# release: slow (~300-500 ms) so it recovers smoothly, not pumping
# No-middleware alternative: tween the Music bus volume down on voice start and
# back up on voice end.
func duck_music(active: bool) -> void:
var target_db := -12.0 if active else 0.0
create_tween().tween_method(
func(v): set_bus_volume_db("Music", v), current_music_db, target_db, 0.25)
3. 音效变化(消除“机关枪式”重复)
# Randomize pitch slightly and pick from a sample pool so repeats feel organic.
func play_varied(samples: Array, bus := "SFX") -> void:
var p := AudioStreamPlayer.new()
p.stream = samples[randi() % samples.size()] # rotate through several takes
p.bus = bus
p.pitch_scale = randf_range(0.94, 1.06) # +/- ~6% pitch wobble
add_child(p); p.play()
p.finished.connect(p.queue_free) # clean up one-shots
4. 节拍同步事件(量化到音乐网格)
# Schedule gameplay/visuals on musical time, not frame time, so they land on beat.
const BPM := 120.0
var seconds_per_beat := 60.0 / BPM
func current_beat(playback_position_sec: float) -> int:
return int(playback_position_sec / seconds_per_beat)
# Quantize an action to the NEXT beat boundary instead of firing immediately.
func time_until_next_beat(pos: float) -> float:
return seconds_per_beat - fmod(pos, seconds_per_beat)
# Drive timing from the audio playback clock, which is steadier than frame delta.
易犯问题
- **把滑块值当作 dB。**音量呈对数关系;应通过
linear_to_db将0..1映射转换(并用db_to_linear转回)。直接控制线性振幅的滑块,直到接近底部时才会让人感觉到变化。 - **逐个片段设置音量,而不是使用总线,**会让全局平衡调整变得不可能,还会使存档/设置臃肿。应通过总线进行混音。
- **Master 削波。**声音叠加后的电平超过 0 dBFS,造成失真。应留出余量;在 Master 上放置限制器作为安全保护,而不是用它来混音。
- **音量衰减产生抽吸感:**释放时间过短或压缩比过高,会让人明显听到音乐的音量起伏。延长释放时间;降低压缩比。
- **整场游戏只循环播放一条音乐音轨,**会让音乐显得平淡。使用会随状态变化的分层或片段(参见参考资料)。
- 根据帧时间进行节拍同步。
delta会产生漂移;应读取音频播放位置来确定音乐时序,并考虑输出延迟。 - **不受限制的一次性播放器:**不断创建 AudioStreamPlayers 却不释放会造成内存泄漏。应在
finished时释放,或使用小型对象池。
参考资料
references/adaptive-music.md— 垂直分层与水平重新编排、转场时机(小节/量化)、点缀音、强度映射和交叉淡化。
相关技能
godot-audio— Godot 中的总线、AudioStreamPlayer、效果和节拍同步。input-systems— 根据输入操作触发音频。physics-tuning— 驱动冲击音效的碰撞事件。platformer、roguelike— 依赖音频反馈营造游戏体验的类型。
评论
支持 Markdown