返回技能市场
开发运维 安全

godot-audio

@admin/godot-audio

在 Godot 中播放与混合音乐和音效,配置音频总线、音量及效果,并实现与节拍同步的播放。

admin 热度 263v0.0.1

Godot 音频 (4.x)

播放 SFX 和音乐,将它们通过总线路由,以分贝控制音量,并将游戏玩法与节拍同步。目标为 Godot 4.7

何时使用

  • 在播放音效或音乐、将音频路由到总线(Master/Music/SFX)、通过代码调整音量/静音、添加总线效果(混响、压缩器)、定位 3D 音频,或将事件同步到音乐时使用。

**何时*不*使用:** 与引擎无关的音频*设计*(自适应音乐结构、混音理念、闪避模式)→ audio-design;在 Godot 之外导入/编码资产。

核心工作流

  1. 选择播放器节点:
  • AudioStreamPlayer — 非定位(音乐、UI、全局 SFX)。
  • AudioStreamPlayer2D / AudioStreamPlayer3D — 定位;音量和声像由距离决定。
  1. AudioStream 分配给 stream(音乐/循环使用 .ogg,短音效使用 .wav),然后调用 play()。对于随场景开始播放的音乐,设置 autoplay
  2. 路由到总线。 将播放器的 bus 设置为命名总线(例如 "Music""SFX")。在音频面板(底部停靠栏)中定义总线;每条总线都可以具有音量、静音、独奏和效果。
  3. 以 dB 控制音量,而不是线性(音频是对数)。0 dB = 不变,-80 dB ≈ 静音。使用 linear_to_db/db_to_linear 转换。
  4. 通过代码驱动音量/静音,使用 AudioServer 按总线索引。
  5. 对于节奏,使用输出延迟补偿计算精确播放时间。

模式

1. 一次性 SFX(发射后不管)

@onready var sfx: AudioStreamPlayer = $Sfx   # stream assigned in the editor

func play_jump() -> void:
    sfx.pitch_scale = randf_range(0.95, 1.05)   # slight variation avoids fatigue
    sfx.play()

# For many overlapping copies, use an AudioStreamPlayer with an
# AudioStreamPolyphonic stream, or spawn short-lived players and free on `finished`.

2. 通过 AudioServer 设置总线音量和静音

func set_music_volume(linear_0_to_1: float) -> void:
    var bus := AudioServer.get_bus_index("Music")
    # Convert a 0..1 slider to decibels; clamp avoids -inf at 0.
    AudioServer.set_bus_volume_db(bus, linear_to_db(maxf(linear_0_to_1, 0.0001)))

func toggle_sfx(muted: bool) -> void:
    AudioServer.set_bus_mute(AudioServer.get_bus_index("SFX"), muted)

3. 在两条音乐轨道之间交叉淡入淡出

@onready var a: AudioStreamPlayer = $MusicA
@onready var b: AudioStreamPlayer = $MusicB

func crossfade_to(stream: AudioStream, secs := 1.5) -> void:
    b.stream = stream
    b.volume_db = -40.0
    b.play()
    var tw := create_tween().set_parallel(true)
    tw.tween_property(a, "volume_db", -40.0, secs)   # fade out current
    tw.tween_property(b, "volume_db", 0.0, secs)     # fade in next
    tw.chain().tween_callback(a.stop)
    var tmp := a; a = b; b = tmp                      # swap roles

4. 精确节拍计时(补偿输出延迟)

@onready var music: AudioStreamPlayer = $Music

func get_playback_time() -> float:
    # Add time since the last audio mix, subtract output latency, for sub-frame accuracy.
    var t := music.get_playback_position() + AudioServer.get_time_since_last_mix()
    return t - AudioServer.get_output_latency()

常见陷阱

  • 将音量视为线性。 volume_db/set_bus_volume_db 是分贝。设置 volume_db = 0.5 接近满音量,而不是一半。使用 linear_to_db 映射滑块。
  • linear_to_db(0.0)-inf 转换前将线性值限制到一个很小最小值(例如 0.0001),或特殊处理 0 → 静音。
  • 总线名称拼写错误会静默失败。 get_bus_index("Muisc") 返回 -1;后续调用会错误或无操作。匹配音频面板中的确切总线名称。
  • 短音效会被截断,当同一播放器被重新触发时。使用单独播放器、AudioStreamPolyphonic,或每次触发创建 AudioStreamPlayer 并在 finished 时释放。
  • 音乐不会循环,除非导入/流循环已启用(.ogg 导入有 Loop 选项;AudioStreamWAVloop_mode)。
  • 仅使用 get_playback_position() 同步会抖动 — 它按音频混合更新,而不是按帧更新;添加 get_time_since_last_mix() 并减去 get_output_latency()
  • 3D 音频听不见 → 没有 AudioListener3D/Camera3D 来听到它,或 max_distance/衰减太紧,或错误总线被静音。

参考

  • 有关总线布局(.tres)、添加效果(混响/压缩器/EQ)和侧链闪避、AudioStreamPolyphonic/AudioStreamInteractive、麦克风捕获,以及使用 AudioStreamGenerator 的程序化音频,请阅读 references/buses-and-effects.md

相关技能

  • audio-design — 与引擎无关的自适应音乐、混音和闪避实践。
  • godot-animation — 将动画/Tween 同步到 get_playback_position()
  • godot-ui-control — 将音量滑块连接到 AudioServer
qianwen skills install @admin/godot-audio