mcpField
A
audio-system

audio-system

github.com/jame581开发889179 次安装4 天前更新
代码仓库

关于 audio-system

面向 Godot 4.3+ 游戏开发者的音频系统技能指南,提供 GDScript 和 C# 示例。内容包括总线、空间音频、音乐管理、音效池、设置保存和自适应音乐。

主要功能

  1. 01音频总线路由与效果
  2. 022D 和 3D 空间播放
  3. 03通过 Autoload 淡入淡出音乐
  4. 04池化音效播放器
  5. 05保存音量设置
  6. 06自适应音乐流模式

适用场景

  1. 01分别调节音乐、音效和 UI 音量
  2. 02播放定位于游戏世界的声音
  3. 03在场景切换时交叉淡化音乐
  4. 04限制频繁音效播放时的播放器创建

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jame581/godotprompter --skill audio-system

安装后在 Claude Code 中输入/audio-system确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
audio-settings.md
interactive-music.md
music-manager.md
sfx-pooling.md

详细介绍

Godot 4.3+ 中的音频系统

所有示例均适用于 Godot 4.3+,不使用已弃用的 API。先展示 GDScript,再展示 C#。

**相关技能:**使用 event-bus 解耦音频触发,使用 save-load 持久化音频设置,使用 resource-pattern 创建音频数据容器。


1. 核心概念

音频节点类型
节点维度用途
AudioStreamPlayer非定位音频音乐、UI 音效、全局音效
AudioStreamPlayer2D2D 定位音频脚步声、枪声、环境音效
AudioStreamPlayer3D3D 定位音频与 2D 相同,但在 3D 空间中
音频总线架构

Godot 会将所有音频通过总线路由(类似混音台)。

Master (always exists)
├── Music          → volume, effects for background music
├── SFX            → volume, effects for sound effects
│   ├── Footsteps  → sub-bus for fine-tuning
│   └── Weapons    → sub-bus for fine-tuning
└── UI             → volume for menu sounds

**设置:**底部面板 → Audio 标签页 → 添加总线、设置名称并路由输出。

每个 AudioStreamPlayer 都有一个 bus 属性——将其设为目标总线名称(例如 "SFX"、"Music")。


2. 基本音频播放

GDScript
extends Node2D

@onready var sfx_player: AudioStreamPlayer2D = $AudioStreamPlayer2D
@onready var music_player: AudioStreamPlayer = $MusicPlayer

func _ready() -> void:
    # Play background music (looping is set on the AudioStream resource)
    music_player.play()

func play_jump_sound() -> void:
    sfx_player.stream = preload("res://audio/sfx/jump.wav")
    sfx_player.play()
C#
using Godot;

public partial class AudioExample : Node2D
{
    private AudioStreamPlayer2D _sfxPlayer;
    private AudioStreamPlayer _musicPlayer;

    public override void _Ready()
    {
        _sfxPlayer = GetNode<AudioStreamPlayer2D>("AudioStreamPlayer2D");
        _musicPlayer = GetNode<AudioStreamPlayer>("MusicPlayer");
        _musicPlayer.Play();
    }

    public void PlayJumpSound()
    {
        _sfxPlayer.Stream = GD.Load<AudioStream>("res://audio/sfx/jump.wav");
        _sfxPlayer.Play();
    }
}
循环播放音频

循环播放在 AudioStream 资源上配置,而不是在播放器节点上:

  • **WAV:**Import 标签页 → Loop Mode → Forward(或 Ping-Pong)
  • **OGG:**Import 标签页 → Loop → On,设置 Loop Offset
  • **MP3:**Import 标签页 → Loop → On

音乐始终使用 OGG Vorbis(文件更小,音质良好)。短音效使用 WAV(PCM 或 QOA,解码开销低)。避免将 MP3 用于音效——视编码器而定,开头可能会有填充静音。


3. 音频总线管理

在代码中设置音量

Godot 使用**分贝(dB)**表示音量。滑块需要进行线性值到 dB 的转换。

GDScript
# Get bus index by name
var bus_index: int = AudioServer.get_bus_index("SFX")

# Set volume in dB directly
AudioServer.set_bus_volume_db(bus_index, -6.0)  # -6 dB ≈ half amplitude (db_to_linear(-6.0) ≈ 0.5)

# Convert linear (0.0–1.0) to dB — use for UI sliders
func set_bus_volume_linear(bus_name: String, linear: float) -> void:
    var index := AudioServer.get_bus_index(bus_name)
    AudioServer.set_bus_volume_db(index, linear_to_db(linear))

# Mute / unmute a bus
AudioServer.set_bus_mute(bus_index, true)

# Read current volume as linear (for displaying on a slider)
func get_bus_volume_linear(bus_name: String) -> float:
    var index := AudioServer.get_bus_index(bus_name)
    return db_to_linear(AudioServer.get_bus_volume_db(index))
C#
int busIndex = AudioServer.GetBusIndex("SFX");

// Set volume in dB
AudioServer.SetBusVolumeDb(busIndex, -6.0f);

// Linear to dB conversion for UI sliders
public void SetBusVolumeLinear(string busName, float linear)
{
    int index = AudioServer.GetBusIndex(busName);
    AudioServer.SetBusVolumeDb(index, Mathf.LinearToDb(linear));
}

// Mute / unmute
AudioServer.SetBusMute(busIndex, true);

// Read current volume as linear
public float GetBusVolumeLinear(string busName)
{
    int index = AudioServer.GetBusIndex(busName);
    return Mathf.DbToLinear(AudioServer.GetBusVolumeDb(index));
}
音频总线效果

在 Audio 面板(底部停靠面板)中为总线添加效果。常见效果:

效果用途
Reverb洞穴、大教堂、浴室的环境音效
Delay回声效果
Compressor标准化响亮或轻柔的声音(主总线)
HardLimiter防止主总线发生削波(Limiter 已弃用)
LowPassFilter模糊音效(水下、隔墙)
HighPassFilter单薄、尖细的声音(收音机、电话)
Chorus让声音更厚实
Distortion粗粝、过载效果
EQ微调频段
动态切换效果
# Enable/disable an effect on a bus at runtime
var bus_index := AudioServer.get_bus_index("SFX")
var effect_index := 0  # First effect on the bus
AudioServer.set_bus_effect_enabled(bus_index, effect_index, true)

# Apply low-pass filter for "underwater" feel
func set_underwater(enabled: bool) -> void:
    var index := AudioServer.get_bus_index("SFX")
    # Assumes a LowPassFilter is the first effect on the SFX bus
    AudioServer.set_bus_effect_enabled(index, 0, enabled)

4. 空间音频(2D 和 3D)

AudioStreamPlayer2D

根据声音源与当前 AudioListener2D 的距离(如果没有当前监听器,则与屏幕中心的距离),自动调整音量和声像。

Enemy (CharacterBody2D)
├── Sprite2D
└── AudioStreamPlayer2D   ← positioned at enemy's location
    bus = "SFX"
    max_distance = 1000.0
    attenuation = 1.0

关键属性:

属性描述默认值
max_distance超过此距离后,声音将静音2000.0
attenuation音量衰减曲线(1.0 = 线性,值越大衰减越陡)1.0
max_polyphony此播放器可同时播放的最大实例数1
panning_strength声音左右声像移动的幅度1.0
AudioStreamPlayer3D

概念相同,但用于 3D。可与 AudioListener3D(或 Camera3D)配合使用。

其他关键属性:

属性描述
unit_size音量为 0 dB 时对应的距离
max_db最大音量上限
attenuation_modelInverse、InverseSquare、Logarithmic、Disabled
doppler_tracking为移动声源启用多普勒效应
AudioListener
# Make a specific camera the audio listener
# 2D: add AudioListener2D as child of Camera2D, call make_current()
# 3D: add AudioListener3D as child of Camera3D, call make_current()

# By default, the current Camera2D/3D acts as the listener.
# Only add an explicit AudioListener if you need a different listening position.
// 2D spatial player
public partial class Footsteps : AudioStreamPlayer2D
{
    public override void _Ready()
    {
        Bus = "SFX";
        MaxDistance = 1000.0f;     // Pixels at which volume reaches zero
        Attenuation = 1.0f;         // Linear falloff (higher = sharper)
        MaxPolyphony = 4;           // Allow overlapping footstep sounds
    }

    public void PlayStep() => Play();
}

// 3D spatial player
public partial class EngineHum : AudioStreamPlayer3D
{
    public override void _Ready()
    {
        Bus = "SFX";
        UnitSize = 4.0f;            // Meters at which volume is 0 dB
        MaxDistance = 50.0f;
        AttenuationModel = AttenuationModelEnum.InverseDistance;
    }
}

// Custom listener — overrides the default Camera2D / Camera3D listener.
public partial class FollowCamListener : AudioListener3D
{
    public override void _Ready() => MakeCurrent();
}

⚠️ Godot 4.7 中的变更:AudioStreamPlayer2D/AudioStreamPlayer3D 的默认 area_mask 从 1 改为 0(禁用)——对于仍使用默认值的播放器,Area2D/Area3D 上的 audio_bus_override 功能(例如水下总线)将停止工作。将 area_mask 设回第 1 层即可恢复;显式设为第 1 层以外值的遮罩不受影响。(迁移指南中提到的是“AudioStreamPlayer”,但 area_mask 仅存在于 2D/3D 变体中。)请参阅 4.7 迁移指南。


5. 音乐管理器(自动加载)

通过管理两个 AudioStreamPlayer 节点并对它们的 volume_db 进行补间的单例自动加载,在背景曲目之间交叉淡化。连接一个 Music 音频总线,让设置菜单可以单独调节音乐音量。

完整的 GDScript 和 C# 自动加载实现(交叉淡化、淡出停止、音乐总线音量)请参阅 references/music-manager.md。


6. 音效池

预先实例化一组固定数量的 AudioStreamPlayer 节点;play_sfx(stream) 会找到下一个空闲的播放器并播放。对于高频音效(枪声、脚步声、命中声),这种方式可以避免每次播放都实例化节点带来的开销。

GDScript 和 C# 的播放器池实现,以及 2D 定位音效变体(由跟随目标的 AudioStreamPlayer2D 节点组成的池),请参阅 references/sfx-pooling.md。


7. 音频设置集成

将设置菜单中的 HSlider 连接到总线音量,通过 AudioServer.set_bus_volume_db(bus_idx, linear_to_db(value)) 进行设置。使用 ConfigFile 保存设置。请使用 linear_to_db / db_to_linear 辅助函数,切勿手动取对数。

包含持久化功能的完整设置菜单连接示例(GDScript + C#)请参阅 references/audio-settings.md。


8. 交互式与自适应音乐(Godot 4.3+)

自适应音乐有三种流类型:AudioStreamPlaylist(按顺序或随机播放曲目)、AudioStreamSynchronized(多个音轨同步播放——用于随战斗强度变化的垂直分层)、AudioStreamInteractive(由触发条件切换片段——由状态驱动的音乐)。Godot 4.4+ 添加了 AudioStreamWAV.load_from_file(),用于在运行时加载 WAV。

Godot 4.7+:AudioStreamInteractive 现在向脚本公开了 TRANSITION_TO_TIME_PREVIOUS_POSITION(TransitionToTime 枚举)——如果之前曾从目标片段切换过来,则目标片段会从上次播放的位置继续;否则从头播放。非常适合在探索音乐 ↔ 战斗音乐之间切换,并从中断处继续播放。

流类型对比、GDScript 示例、4.7+ 的续播位置切换,以及 4.4+ 的运行时加载示例,请参阅 references/interactive-music.md。


9. 音频导入最佳实践

格式用途文件大小解码延迟循环支持
WAV短音效大无(PCM)/ 轻微(QOA,4.4+ 默认)通过导入
OGG音乐、长音效小极低通过导入
MP3音乐(备用)小存在填充通过导入
导入设置

在导入面板中(选择音频文件):

  • Loop: 为音乐和环境循环启用
  • BPM / Beat Count / Bar Beats: 为节奏同步游戏设置
  • Force Mono(仅 WAV):为 3D 定位音频启用(立体声不适合空间化);在音频编辑器中将 OGG/MP3 导出为单声道

**提示:**音效使用 16 位、44.1kHz 的 WAV。将 WAV 导入设置中的 Compress > Mode 设为 PCM(未压缩),可实现零解码开销——4.4+ 默认使用 QOA(4.3 默认使用 PCM,标记为 Disabled)。音乐使用质量 6–8 的 OGG Vorbis,可获得良好平衡。


11. 常见问题

现象原因解决方法
声音无法播放播放器未添加到场景树中确保在调用 play() 前通过 add_child() 添加 AudioStreamPlayer
声音正在播放,但听不到音频总线已静音或音量调低在 Audio 面板中检查总线;拼写错误的 bus 名称会回退到 Master(绕过你的总线)
切换场景后音乐重新开始播放器属于场景,而不是自动加载将音乐播放器移至自动加载项(MusicManager)
3D 定位音频无声没有当前的 Camera3D 或 AudioListener3D(2D 使用屏幕中心)添加 AudioListener3D,或确保 Camera3D 处于当前状态
声音出现咔哒声或爆音音频文件没有淡入/淡出在音频编辑器中为 WAV 的开头/结尾添加极短的淡入淡出(2–5ms)
同时播放的声音过多未限制复音数在播放器上设置 max_polyphony,或使用 SFX 池
音量滑块感觉不是线性的直接使用 dB,而不是进行线性转换对滑块值使用 linear_to_db() / db_to_linear()
3D 音频听起来像单声道/平淡使用了立体声音源文件3D 空间化请使用单声道文件(WAV:在 Import 标签页中选择 Force Mono)
MP3 开头有静音文件中存在编码器填充对时序要求严格的 SFX 使用 WAV,音乐使用 OGG

12. 实现检查清单

  • 已设置音频总线:Master、Music、SFX(至少这些)
  • 所有 AudioStreamPlayer 节点都已指定正确的 bus 属性
  • 音乐使用 OGG Vorbis 格式;较短的 SFX 使用 WAV
  • 音乐播放器位于自动加载项中(切换场景后仍可继续播放)
  • 已实现音乐交叉淡化,以实现平滑过渡
  • 使用 SFX 池,而不是动态创建新的 AudioStreamPlayer 节点
  • 音量滑块使用 linear_to_db() / db_to_linear() 转换
  • 接近零的滑块值会将总线静音(避免 linear_to_db(0.0) = -inf)
  • 3D 音频源使用单声道音频文件,以实现正确的空间化
  • 音频设置会在游戏启动时保存并恢复(使用 ConfigFile 或类似方式)
  • 循环播放在 AudioStream 资源中配置,而不是在代码中配置
  • 交互式/自适应音乐使用 AudioStreamPlaylist、AudioStreamSynchronized 或 AudioStreamInteractive(Godot 4.3+),而不是手动切换曲目的代码

评论

支持 Markdown