谢夏戈 @ xiexiage.com

音效 SoundManager

May 12

游戏没声音就像炒菜没盐 — 没那个味儿。这一章加上:

  • 🪶 翅膀扇动声(小鸟跳跃时)
  • 得分声(穿过水管时)
  • 💥 碰撞声(撞死时)

准备音效文件

我用的音效来源:TODO 素材链接

免费音效推荐:

需要 3 个文件,放到 audio/ 目录下:

  • wing.wav — 扑翅膀
  • score.wav — 得分
  • strike.wav — 撞击

08-sound-音效文件

💡 推荐用 .wav 而不是 .mp3:体积大一点,但延迟低、循环不卡顿。短音效用 wav 是标配。

SoundManager 是个场景,不是脚本

和 GameManager 不一样,SoundManager 我们用 场景(.tscn) 来做,而不是单纯的脚本。

为什么? 因为每个音效都需要一个 AudioStreamPlayer 节点 — 与其在脚本里 new AudioStreamPlayer(),不如直接在场景里把所有 player 节点摆好,音效文件也提前在 Inspector 里预设好,调用时直接 .play() 就行。

创建 SoundManager 场景

新建场景,保存为 scenes/autoload/sound_manager.tscn

使用到的节点:

  • Node(重命名 SoundManager)— 根节点
    • Node(重命名 SFX)— 音效组
      • AudioStreamPlayer(重命名 wing_sfx
      • AudioStreamPlayer(重命名 score_sfx
      • AudioStreamPlayer(重命名 strike_sfx

08-sound-scene-结构

每个 AudioStreamPlayer 的设置

选中每个 player,在右侧 Inspector 里:

  • Stream:拖入对应的音效文件(如 wing.wav 拖到 wing_sfx 的 Stream 槽)
  • Volume dB:根据音量调整(-6 dB 是温和的衰减,-12 dB 是明显的降低)

08-sound-audiostreamplayer

SoundManager 脚本

给根节点挂脚本 sound_manager.gd

extends Node

# 在检查器里预载好你的音效文件
@onready var score_sfx: AudioStreamPlayer = $SFX/score_sfx
@onready var strike_sfx: AudioStreamPlayer = $SFX/strike_sfx
@onready var wing_sfx: AudioStreamPlayer = $SFX/wing_sfx

func play_score():
    score_sfx.play()

func play_die():
    strike_sfx.play()

func play_wing():
    wing_sfx.play()
  • @onready var xxx = $SFX/xxx — 拿到子节点的引用
  • 方法本身就一行:调用对应 player 的 play() 即可

注册为 Autoload

和 GameManager 一样,项目 → 项目设置 → 全局 → 自动加载

路径节点名称
res://scenes/autoload/sound_manager.tscnSoundManager

08-sound-autoload

⚠️ 注意这里加载的是 场景文件 (.tscn),不是脚本 (.gd)。Godot 的 Autoload 同时支持两者。

在游戏里调用

现在任何节点都能直接喊 SoundManager 一声 — 在合适的位置加上音效调用:

小鸟跳跃时(bird.gd

if Input.is_action_just_pressed("fly"):
    velocity.y = jump_force
    SoundManager.play_wing()  # 👈 加这一行

穿过水管得分时(pillar_pair.gd

func _on_goal_body_entered(body: Node2D) -> void:
    if body.name == "Bird":
        SoundManager.play_score()  # 👈 加这一行
        if GameManager.has_method("add_score"):
            GameManager.add_score(1)
        goal.set_deferred("monitoring", false)

撞死时(killzone.gd

func _on_body_entered(body: Node2D) -> void:
    if body.name == "Bird" and GameManager.current_state == GameManager.GameState.PLAYING:
        SoundManager.play_die()  # 👈 加这一行
        GameManager.game_over()

测试运行

戴上耳机,应该能听到:

  • ✅ 按 fly → 翅膀扇动声
  • ✅ 穿过水管 → 清脆的得分音
  • ✅ 撞死 → 一声闷响

如果声音太大/太小,去 sound_manager.tscn 里调 Volume dB不用改代码

(可选)背景音乐 BGM

你可以再加一个 AudioStreamPlayer(命名 BGM),在 Inspector 里:

  • Stream:拖入背景音乐
  • Autoplay:✅ 勾选(场景一加载就播放)
  • Loop:在 Stream 的导入设置里勾选 Loop

这样游戏一开始就有背景音乐。

下一章我们打包导出游戏,发布到 itch.io!🚀

2023-PRESENT © 谢夏戈