15、音频系统

第15章 音频系统

15.1 AudioStreamPlayer 基础

gdscript 复制代码
# AudioStreamPlayer:非位置音频(BGM、UI音效)
# AudioStreamPlayer2D:2D 位置音频(距离衰减)
# AudioStreamPlayer3D:3D 位置音频

extends AudioStreamPlayer

func _ready() -> void:
    stream = preload("res://audio/bgm/battle_theme.ogg")
    volume_db = -10  # 音量(分贝)
    pitch_scale = 1.0
    autoplay = false
    bus = "Music"  # 音频总线

func play_bgm() -> void:
    if not playing:
        play()

func stop_bgm() -> void:
    if playing:
        # 淡出
        var tween := create_tween()
        tween.tween_property(self, "volume_db", -40.0, 1.0)
        await tween.finished
        stop()
        volume_db = -10  # 恢复音量

15.2 AudioStreamRandomizer(随机音效变体)

gdscript 复制代码
# AudioStreamRandomizer 自动在多个音效中随机选择
# 避免重复播放同一音效产生机械感

# 设置:
# 1. 创建 AudioStreamRandomizer 资源
# 2. 添加多个 AudioStream(如不同的脚步声)
# 3. 设置 Playback Mode: Random (No Repeat)
# 4. 设置 Random Pitch: 0.9 ~ 1.1(音高随机变化)

# 代码使用
extends AudioStreamPlayer2D

func play_footstep() -> void:
    stream = preload("res://audio/sfx/footstep_randomizer.tres")
    pitch_scale = randf_range(0.9, 1.1)  # 额外随机
    play()

15.3 音频总线(Audio Bus)

gdscript 复制代码
# 音频总线用于分组控制音量和效果
# 设置:底部面板 → Audio → Audio Bus

# 推荐总线布局:
# Bus 0: Master(主音量)
# Bus 1: Music(背景音乐)
# Bus 2: SFX(音效)
# Bus 3: Voice(语音)
# Bus 4: Ambient(环境音)

# 代码控制
func set_music_volume(volume_db: float) -> void:
    var bus_idx := AudioServer.get_bus_index("Music")
    AudioServer.set_bus_volume_db(bus_idx, volume_db)

func set_sfx_mute(muted: bool) -> void:
    var bus_idx := AudioServer.get_bus_index("SFX")
    AudioServer.set_bus_mute(bus_idx, muted)

# 添加音频效果
func add_reverb_to_sfx() -> void:
    var bus_idx := AudioServer.get_bus_index("SFX")
    var reverb := AudioEffectReverb.new()
    reverb.room_size = 0.8
    reverb.damping = 0.5
    AudioServer.add_bus_effect(bus_idx, reverb)

15.4 位置音频(AudioStreamPlayer2D)

gdscript 复制代码
extends AudioStreamPlayer2D

func _ready() -> void:
    # 距离衰减设置
    max_distance = 500.0  # 超过这个距离听不到
    # attenuation 属性在 Godot 4.x 中通过衰减曲线控制
    # 默认使用反距离衰减

# 爆炸音效(在特定位置播放)
func play_explosion_sound(pos: Vector2) -> void:
    var sound := AudioStreamPlayer2D.new()
    sound.stream = preload("res://audio/sfx/explosion.wav")
    sound.global_position = pos
    sound.max_distance = 800.0
    add_child(sound)
    sound.play()
    sound.finished.connect(sound.queue_free)

15.5 动态音乐系统

gdscript 复制代码
extends Node

@onready var exploration_player: AudioStreamPlayer = $ExplorationMusic
@onready var combat_player: AudioStreamPlayer = $CombatMusic

var is_in_combat: bool = false
var crossfade_duration: float = 2.0

func enter_combat() -> void:
    if is_in_combat:
        return
    is_in_combat = true
    
    # 交叉渐变
    combat_player.volume_db = -40
    combat_player.play()
    
    var tween := create_tween().set_parallel(true)
    tween.tween_property(exploration_player, "volume_db", -40, crossfade_duration)
    tween.tween_property(combat_player, "volume_db", 0, crossfade_duration)

func exit_combat() -> void:
    if not is_in_combat:
        return
    is_in_combat = false
    
    var tween := create_tween().set_parallel(true)
    tween.tween_property(combat_player, "volume_db", -40, crossfade_duration)
    tween.tween_property(exploration_player, "volume_db", 0, crossfade_duration)
    await tween.finished
    combat_player.stop()

15.6 对话语音

gdscript 复制代码
extends RichTextLabel

@export var voice_stream: AudioStreamPlayer

var is_typing: bool = false
var typing_speed: float = 0.03  # 每个字符的时间

func show_dialogue(text: String, voice: AudioStream = null) -> void:
    visible_characters = 0
    self.text = text
    is_typing = true
    
    if voice and voice_stream:
        voice_stream.stream = voice
        voice_stream.play()
    
    for i in text.length():
        if not is_typing:
            break
        visible_characters = i + 1
        await get_tree().create_timer(typing_speed).timeout
    
    visible_characters = -1  # 显示全部
    is_typing = false

func skip_typing() -> void:
    is_typing = false
    visible_characters = -1
相关推荐
狂人开飞机1 小时前
16、粒子线条与视觉特效
游戏引擎·godot
心前阳光13 小时前
Unity发布PC软件图标不能改变
unity·游戏引擎
an869500120 小时前
unity如何在visual studio中打断点debug
unity·游戏引擎·visual studio
xcLeigh21 小时前
Unity基础:使用Transform控制物体移动——Translate与position详解
unity·游戏引擎
FairGuard手游加固1 天前
Unity小游戏加密:global-metadata.dat与AssetBundle保护
游戏·unity·游戏引擎
狂人开飞机1 天前
11、UI系统
游戏引擎·godot
真鬼1231 天前
【Unity AI】Untiy链接cursor与MCP
unity·游戏引擎
郝学胜-神的一滴1 天前
C++11 工程级应用 10:减少拷贝,让容器跑得更快
服务器·开发语言·c++·游戏引擎·opengl
玖玥拾1 天前
Lua 基础语法(八) Unity Huatuo (HybridCLR)
开发语言·unity·游戏引擎·lua