extends Node ## 最简近距离语音:按住 C(talk)采集麦克风 → 广播给所有对端 → ## 在说话者位置的 RaytracedAudioPlayer3D 回放。 ## 距离衰减/声像由 3D 音频完成,墙体闷音、环境混响由 raytraced_audio 插件完成。 ## 依赖:default_bus_layout.tres 的 mic 总线(静音 + AudioEffectCapture)、 ## RaytracedReverb/RaytracedAmbient 总线(插件用)、player.tscn 根节点下的 Voice 节点。 @export var max_distance := 25.0 var _capture: AudioEffectCapture var _voice_3d: RaytracedAudioPlayer3D var _playback: AudioStreamGeneratorPlayback func _ready() -> void: _capture = AudioServer.get_bus_effect(AudioServer.get_bus_index("mic"), 0) _voice_3d = RaytracedAudioPlayer3D.new() var gen := AudioStreamGenerator.new() gen.mix_rate = 48000.0 # 与 audio/driver/mix_rate 一致,否则变速变调 _voice_3d.stream = gen _voice_3d.position = Vector3(0, 1.5, 0) # 嘴部高度 _voice_3d.max_distance = max_distance add_child(_voice_3d) if is_multiplayer_authority() and DisplayServer.get_name() != "headless": var mic := AudioStreamPlayer.new() mic.stream = AudioStreamMicrophone.new() mic.bus = "mic" add_child(mic) mic.play() # 监听器只建在本地玩家身上(多个监听器会互相抢 current) var listener := RaytracedAudioListener.new() listener.position = Vector3(0, 1.6, 0) # 头部高度 add_child(listener) listener.owner = get_parent() # 插件的 ambient 计算会读 owner,代码创建的节点必须手动指定 else: _voice_3d.play() _playback = _voice_3d.get_stream_playback() func _process(_delta: float) -> void: if not is_multiplayer_authority() or _capture == null: return if not Input.is_action_pressed("talk"): _capture.clear_buffer() # 松开时丢弃积压,避免下次开口带旧音频 return var frames := _capture.get_buffer(_capture.get_frames_available()) if not frames.is_empty(): receive_voice.rpc(frames) @rpc("any_peer", "call_remote", "unreliable_ordered", 1) func receive_voice(frames: PackedVector2Array) -> void: if not _playback: _playback = _voice_3d.get_stream_playback() _playback.push_buffer(frames)