Godot Version
4.5.1
Question
Im new to Godot and want to implement a proximity voice chat and followed a tutorial on Youtube. That didnt work and now I tried to use some AI to help me fix my problem, which is loud static, cracking noise and beeps, but that also didnt work. Does anyone know whats wrong in my code?
extends CharacterBody3D
@onready var player_name_label: Label = %PlayerNameLabel
@onready var camera: Camera3D = %Camera
@onready var kamerapivot: Marker3D = %Kamerapivot
@onready var multiplayer_synchronizer: MultiplayerSynchronizer = %MultiplayerSynchronizer
@onready var prox_network: AudioStreamPlayer3D = $ProxNetwork
@onready var prox_local: AudioStreamPlayer3D = $ProxLocal
var max_frames_per_process := 256
var current_sample_rate: int = 24000
var has_loopback: bool = false
var local_playback: AudioStreamGeneratorPlayback = null
var local_voice_buffer: PackedByteArray = PackedByteArray()
var network_playback: AudioStreamGeneratorPlayback = null
var network_voice_buffer: PackedByteArray = PackedByteArray()
var packet_read_limit: int = 5
@export var player_name:String = "Gubi Fortnite"
@export var steam_id:int = 0
@export var mouse_sensitivity = 0.002
var last_position: Vector3 = Vector3.ZERO
const SPEED = 8.0
const JUMP_VELOCITY = 7.5
func _enter_tree() -> void:
set_multiplayer_authority(name.to_int())
func _ready() -> void:
current_sample_rate = Steam.getVoiceOptimalSampleRate()
if current_sample_rate <= 0:
current_sample_rate = 24000
print(current_sample_rate)
prox_local.stream.mix_rate = current_sample_rate
prox_local.play()
await get_tree().process_frame
local_playback = prox_local.get_stream_playback()
print(prox_local.stream)
print(local_playback)
prox_network.stream.mix_rate = current_sample_rate
prox_network.play()
network_playback = prox_network.get_stream_playback()
add_to_group("players")
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if is_multiplayer_authority():
camera.set_current(true)
sync_player_data.rpc(SteamManager.STEAM_ID)
else:
request_data.rpc_id(get_multiplayer_authority())
@rpc("any_peer", "reliable")
func request_data():
var requester_id = multiplayer.get_remote_sender_id()
sync_player_data.rpc_id(requester_id, SteamManager.STEAM_ID)
@rpc("any_peer", "call_local", "reliable")
func sync_player_data(new_id: int):
player_name = Steam.getFriendPersonaName(new_id)
steam_id = new_id
if player_name_label:
player_name_label.text = player_name
func _unhandled_input(event):
if mouse_sensitivity == null:
return
if event is InputEventMouseMotion:
# Körper horizontal drehen (Y-Achse)
rotate_y(-event.relative.x * mouse_sensitivity)
# Kamera vertikal drehen (X-Achse)
kamerapivot.rotate_x(-event.relative.y * mouse_sensitivity)
# Limitieren, damit man keinen Überschlag macht
kamerapivot.rotation.x = clamp(kamerapivot.rotation.x, deg_to_rad(-80), deg_to_rad(80))
func _physics_process(delta: float) -> void:
if !is_multiplayer_authority():
return
if not is_on_floor():
velocity += get_gravity() * delta
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
var input_dir := Input.get_vector("move_left", "move_right", "move_forward", "move_backwards")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
velocity.x = direction.x * SPEED
velocity.z = direction.z * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.z = move_toward(velocity.z, 0, SPEED)
if velocity.length() > 500 or global_position.distance_to(last_position) > 5.0:
print("reset")
velocity = Vector3.ZERO
position = Vector3.ZERO
last_position = global_position
move_and_slide()
for i in get_slide_collision_count():
var collision = get_slide_collision(i)
var collider = collision.get_collider()
if collider is RigidBody3D:
var push_dir = -collision.get_normal()
var push_force = 150.0 * delta
var total_impulse = push_dir * push_force
collider.apply_push.rpc(total_impulse)
func _input(event: InputEvent) -> void:
if !is_multiplayer_authority():
return
if Input.is_action_just_pressed("voice_record"):
record_voice(true)
elif Input.is_action_just_released("voice_record"):
record_voice(false)
func _process(delta: float) -> void:
if is_multiplayer_authority():
check_for_voice()
func process_voice_data(voice_data:Dictionary, voice_source:String) -> void:
var decompressed_voice: Dictionary
if voice_source == "local":
decompressed_voice = Steam.decompressVoice(voice_data['buffer'], current_sample_rate)
elif voice_source == "network":
decompressed_voice = Steam.decompressVoice(voice_data['voice_data'], current_sample_rate)
if decompressed_voice['result'] == Steam.VOICE_RESULT_OK and decompressed_voice['uncompressed'].size() > 0:
if voice_source == "local":
local_voice_buffer.append_array(decompressed_voice['uncompressed'])
var i := 0
while i + 1 < local_voice_buffer.size():
var raw_value := local_voice_buffer.decode_s16(i)
var sample := clampf(raw_value / 32768.0, -1.0, 1.0)
local_playback.push_frame(Vector2(sample, sample))
i += 2
local_voice_buffer = local_voice_buffer.slice(i)
elif voice_source == "network":
network_voice_buffer.append_array(decompressed_voice['uncompressed'])
if network_voice_buffer.size() < 4096:
return
var frames_available = network_playback.get_frames_available()
var n = 0
for i in range(0, min(frames_available * 2, network_voice_buffer.size() - 1), 2):
var raw_value := network_voice_buffer.decode_s16(i)
var sample := clampf(raw_value / 32768.0, -1.0, 1.0)
network_playback.push_frame(Vector2(sample, sample))
n = i + 2
network_voice_buffer = network_voice_buffer.slice(n)
func record_voice(is_recording: bool) -> void:
Steam.setInGameVoiceSpeaking(SteamManager.STEAM_ID, is_recording)
if is_recording:
Steam.startVoiceRecording()
else:
Steam.stopVoiceRecording()
local_voice_buffer = PackedByteArray()
network_voice_buffer = PackedByteArray()
if local_playback:
var frames := local_playback.get_frames_available()
for _i in range(frames):
local_playback.push_frame(Vector2.ZERO)
func check_for_voice() -> void:
var available_voice: Dictionary = Steam.getVoice()
if available_voice['result'] == Steam.VOICE_RESULT_OK and available_voice['buffer'].size() > 0:
if available_voice['result'] == Steam.VOICE_RESULT_OK:
SteamManager.send_voice_data(available_voice['buffer'])
if has_loopback:
process_voice_data(available_voice, "local")
func get_sample_rate(is_toggled: bool = true) -> void:
if is_toggled:
current_sample_rate = Steam.getVoiceOptimalSampleRate()
else:
current_sample_rate = 24000
prox_network.stream.mix_rate = current_sample_rate
prox_local.stream.mix_rate = current_sample_rate
extends Node
const PACKET_READ_LIMIT: int = 32
var STEAM_APP_ID:int = 480
var STEAM_USERNAME:String = ""
var STEAM_ID:int = 0
var is_lobby_host:bool = false
var lobby_id:int = 0
var lobby_members:Array
#var peer:SteamMultiplayerPeer = SteamMultiplayerPeer.new()
func _ready() -> void:
print("Steam initialized: ", Steam.steamInit(STEAM_APP_ID, true))
Steam.initRelayNetworkAccess()
STEAM_ID = Steam.getSteamID()
print(STEAM_ID)
STEAM_USERNAME = Steam.getPersonaName()
print(STEAM_USERNAME)
Steam.lobby_joined.connect(_on_lobby_joined)
Steam.p2p_session_request.connect(_on_p2p_session_request)
func _process(_delta: float) -> void:
if lobby_id > 0:
read_all_p2p_msg_packets()
read_all_p2p_voice_packets()
Steam.run_callbacks()
func _on_lobby_joined(this_lobby_id:int, _permissions:int, _locked:bool, response:int):
if response == Steam.CHAT_ROOM_ENTER_RESPONSE_SUCCESS:
lobby_id = this_lobby_id
get_lobby_members()
make_p2p_handshake()
func _on_p2p_session_request(remote_id:int):
Steam.acceptP2PSessionWithUser(remote_id)
func make_p2p_handshake():
send_p2p_packet(0, {"message" : "handshake", "steam_id" : STEAM_ID, "username" : STEAM_USERNAME}, Steam.P2P_SEND_UNRELIABLE)
func send_voice_data(voice_data: PackedByteArray):
send_p2p_packet(1, {"voice_data" : voice_data, "steam_id" : STEAM_ID, "username" : STEAM_USERNAME}, Steam.P2P_SEND_UNRELIABLE)
func send_p2p_packet(this_target: int, packet_data: Dictionary, send_type: int = 0):
var channel:int = 0
var this_data: PackedByteArray
this_data.append_array(var_to_bytes(packet_data))
if this_target == 0:
if lobby_members.size() > 1:
for member in lobby_members:
if member["steam_id"] != STEAM_ID:
Steam.sendP2PPacket(member["steam_id"], this_data, send_type, channel)
elif this_target == 1:
if lobby_members.size() > 1:
for member in lobby_members:
if member["steam_id"] != STEAM_ID:
Steam.sendP2PPacket(member["steam_id"], this_data, send_type, 1)
else:
Steam.sendP2PPacket(this_target, this_data, send_type, channel)
func get_lobby_members():
lobby_members.clear()
var num_of_lobby_members: int = Steam.getNumLobbyMembers(lobby_id)
for member in range(0,num_of_lobby_members):
var member_steam_id: int = Steam.getLobbyMemberByIndex(lobby_id, member)
var member_steam_name: String = Steam.getFriendPersonaName(member_steam_id)
lobby_members.append({
"steam_id": member_steam_id,
"steam_name": member_steam_name,
})
func read_all_p2p_msg_packets(read_count : int = 0):
if read_count >= PACKET_READ_LIMIT:
return
if Steam.getAvailableP2PPacketSize() > 0:
read_p2p_msg_packet()
read_all_p2p_msg_packets(read_count + 1)
func read_all_p2p_voice_packets(read_count : int = 0):
if read_count >= PACKET_READ_LIMIT:
return
if Steam.getAvailableP2PPacketSize(1) > 0:
read_p2p_voice_packet()
read_all_p2p_voice_packets(read_count + 1)
func read_p2p_msg_packet():
var packet_size: int = Steam.getAvailableP2PPacketSize(0)
if packet_size > 0:
var this_packet: Dictionary = Steam.readP2PPacket(packet_size, 0)
var packet_sender: int = this_packet["remote_steam_id"]
var packet_code: PackedByteArray = this_packet["data"]
var readable_data: Dictionary = bytes_to_var(packet_code)
if readable_data.has("message"):
match readable_data["message"]:
"handshake":
print("PLAYER: ", readable_data["username"], " has joined!")
get_lobby_members()
func read_p2p_voice_packet():
var packet_size: int = Steam.getAvailableP2PPacketSize(1)
if packet_size > 0:
var this_packet: Dictionary = Steam.readP2PPacket(packet_size, 1)
var packet_sender: int = this_packet["remote_steam_id"]
var packet_code: PackedByteArray = this_packet["data"]
var readable_data: Dictionary = bytes_to_var(packet_code)
if readable_data.has("voice_data"):
print("reading ", readable_data["username"], "'s voice data.")
var players_in_scene: Array = get_tree().get_nodes_in_group("players")
print("packet_sender:", packet_sender)
print("players_in_scene size:", players_in_scene.size())
print("players_in_scene:", players_in_scene)
for player in players_in_scene:
print("checking player:", player.name, "steam:", player.steam_id)
if player.steam_id == packet_sender:
player.process_voice_data(readable_data, "network")
else:
pass