Help with players in multiplaye7

Godot Version

4.3

Question

My godot game is glitching where if there is more than 3 players. 1 of the players has The camera is on the host, But for the other 2 players it is fine.

Lobby script:

extends Node3D

class_name lobby


@onready var label: Label = %Label
var port: int = 35565
const DEFAULT_SERVER_IP: String = "127.0.0.1" # IPv4 localhost
const MAX_CONNECTIONS: int = 3



func _physics_process(delta: float) -> void:
	var fps: float = Engine.get_frames_per_second()
	$Label2.text = "FPS: " +str(fps)
	print("Connected Players: ", multiplayer.get_peers().size())


static var peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new()
@export var player_scene : PackedScene



func _on_host_pressed() -> void:
	peer.create_server(port, MAX_CONNECTIONS)
	multiplayer.multiplayer_peer = peer
	multiplayer.peer_connected.connect(add_player)
	add_player()
	
	$CanvasLayer.hide()
	


func _on_join_pressed(address: String = str($CanvasLayer/LineEdit.text)) -> void:
	peer.create_client(address, port)
	if address.is_empty() or address == "localhost":
		address = DEFAULT_SERVER_IP
	multiplayer.multiplayer_peer = peer
	
	$CanvasLayer.hide()
	
	

func add_player(id: int = 1) -> void:
	var player: CharacterBody3D = player_scene.instantiate()
	player.name = str(id)
	call_deferred("add_child", player)
	

func exit_game(id: int) -> void:
	multiplayer.peer_disconnected.connect(del_player)
	del_player(id)


func del_player(id: int) -> void:
	rpc("_del_player" ,id)
	
@rpc("any_peer","call_local")
func  _del_player(id: int) -> void:
	get_node(str(id)).queue_free()
	

func _on_connected_fail() -> void:
	multiplayer.multiplayer_peer = null


func _on_area_3d_body_entered(body: player) -> void:
	body.collision_shape_3d.set_deferred("disabled", false)
	body.sword.show()
	
	
	
	


func _on_area_3d_body_exited(body: player) -> void:
	body.collision_shape_3d.set_deferred("disabled", true)
	body.sword.hide()
	




func _on_endmatch_body_entered(body: player) -> void:
	print(body.label_3d.text, " Won PARKORE")
	%Label.text = str(body.label_3d.text, " Won PARKORE. Go Back To Lobby OR Start Again")
	$parkore/endmatch/CollisionShape3D.set_deferred("disabled", true)
	
	


func _on_startmatch_body_entered(body: player) -> void:
	$parkore/endmatch/CollisionShape3D.set_deferred("disabled", false)
	%Label.text = str("")


func lobby_text_1(strin: String, strin2: String, strin3: String) -> void:
	%Label.text = str(strin, strin2, strin3)


func _on_laser_body_entered(body: player) -> void:
	body.position = Vector3(0, 11, -422.563)

func change_username(Name: String):
	Firebase.Auth.update_account()


func _on_laser_2_body_entered(body: player) -> void:
	body.position = Vector3(241.699, 20.7, -422.12)


func _on_laser_3_body_entered(body: player) -> void:
	body.position = Vector3(150.066, 20.7, -142.723)

Player script:

extends CharacterBody3D


class_name player

var check: int = 0
const SPEED = 7.25
const JUMP_VELOCITY = 6
var platform_name: String = OS.get_name()
@onready var label_3d: Label3D = %Label3D
var json: JSON = JSON.new()
@onready var touch_controls: CanvasLayer = $CanvasLayer
@export var max_health: int = 100
var players_killed: int = 0
var health: int = 100
var saveusername: FileAccess = FileAccess.open("user://username.save", FileAccess.READ)
@onready var sword: Area3D = $Camera_Controller/Camera_Target/Camera3D2/sword
var Player_killed: bool = false
@warning_ignore("narrowing_conversion")
var sens: int = 0.0025
@onready var pivot: Node3D = $Camera_Controller
@onready var collision_shape_3d: CollisionShape3D = $Camera_Controller/Camera_Target/Camera3D2/sword/CollisionShape3D
const JUMP_FORCE = 6
const WALL_JUMP_FORCE = 100
@onready var cam: Camera3D = $Camera_Controller/Camera_Target/Camera3D
@onready var cam_2: Camera3D = $Camera_Controller/Camera_Target/Camera3D2


func _enter_tree() -> void:
	set_multiplayer_authority(name.to_int())

func  _ready() -> void:
	cam.current = is_multiplayer_authority()
	cam_2.current = is_multiplayer_authority()
	
	if platform_name == "Android" or platform_name == "iOS" or platform_name == "Web":
		touch_controls.visible = true
	else:
		touch_controls.visible = false
	$Label3D.text = str(saveusername.get_line())
	

func jump() -> void:
	velocity.y = JUMP_VELOCITY

func slide_jump(z: float) -> void:
	velocity.y = JUMP_VELOCITY
	velocity.z = z




# Get the gravity from the project settings to be synced with RigidBody nodes.
static var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") as float






func _physics_process(delta: float) -> void:
	if is_multiplayer_authority():
		#Rotate the camera left / right
		if Input.is_action_just_pressed("cam_left"):
			$Camera_Controller.rotate_y(deg_to_rad(30))
		
		
		if Input.is_action_just_pressed("cam_right"):
			$Camera_Controller.rotate_y(deg_to_rad(-30))
		
		if Input.is_action_just_pressed("first_person"):
			cam_2.set_current(true)
			cam.set_current(false)
		
		
		if Input.is_action_just_pressed("third_person"):
			cam.set_current(true)
			cam_2.set_current(false)
			
		
		if Input.is_action_just_pressed("quit"):
			$"../".exit_game(name.to_int())
			get_tree().change_scene_to_file("res://menu.tscn")
		
		if Input.is_action_just_pressed("test_parkore"):
			$".".global_position.x = 0
			$".".global_position.y = 15
			$".".global_position.z = -422.563
		
		if Input.is_action_just_pressed("test_parkore_jungle"):
			$".".global_position = Vector3(241.699, 25.135, -422.12)
			$MeshInstance3D.show()
			
		
		if Input.is_action_just_pressed("test_parkore_sea"):
			$".".global_position = Vector3(478.202, 25.135, -407.279)
			$MeshInstance3D.show()
		
		
		if Input.is_action_just_pressed("respawn"):
			$".".global_position.x = 0
			$".".global_position.y = -17.84
			$".".global_position.z = 0
			$MeshInstance3D.show()
			health = max_health
		
		if Input.is_action_just_pressed("restest2"):
			$".".global_position.x = 51.815
			$".".global_position.y = 130.088
			$".".global_position.z = -1053.836
			$MeshInstance3D.show()
			
		
		
		if Input.is_action_just_pressed("test_sword"):
			$".".global_position = Vector3(-116.286, 20.648, 0)
			$MeshInstance3D.show()
		
		if Input.is_action_just_pressed("attack_player"):
			attack()
			if $Camera_Controller/Camera_Target/Camera3D2/sword.is_visible_in_tree():
				$Camera_Controller/Camera_Target/Camera3D2/sword/CollisionShape3D2.set_deferred("disabled", false)
			
			
		if Input.is_action_just_released("attack_player"):
			undo_attack()
			$Camera_Controller/Camera_Target/Camera3D2/sword/CollisionShape3D2.set_deferred("disabled", true)
		
		if Input.is_action_just_pressed("unfocus"):
			%LineEdit.show()
			
			
		
		if Input.is_action_just_pressed("disname"):
			%Label3D.text = str(%LineEdit.text)
		
		if Input.is_action_just_pressed("unfocus2"):
			%LineEdit.hide()
			
		
		# Add the gravity.
		if not is_on_floor():
			velocity.y -= gravity * delta
			
			
		# Handle jump.
		if Input.is_action_just_pressed("ui_accept") and is_on_floor():
			velocity.y = JUMP_VELOCITY
		
		
		
		if is_on_wall_only() and Input.is_action_just_pressed("ui_accept"):
			var normal: Vector3 = get_last_slide_collision().get_normal()
			velocity.y += JUMP_FORCE
			velocity += normal * WALL_JUMP_FORCE
		
		
		
		
		
		
		
		
		
		
		
		# Get the input direction and handle the movement/deceleration.
		# New Vector3 direction, taking into account the user arrow inputs and the camera rotation
		var input_dir: Vector2 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
		Vector2(0,0)
		var direction: Vector3 = ($Camera_Controller.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
		
		# Rotate the character mesh so oriented towards the direction moving in relation to the camera
		if input_dir != Vector2(0,0):
			$MeshInstance3D.rotation_degrees.y = $Camera_Controller.rotation_degrees.y -rad_to_deg(input_dir.angle())
		
		
		
		
		
		# Update the velocity and move the character
		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)
			
		move_and_slide()
		
		
		
		
		
		
		
		
		



	

func _unhandled_input(event: InputEvent) -> void:
	if is_multiplayer_authority():
		if event is InputEventMouseButton:
			Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
		elif event.is_action_pressed("show_mouse"):
			Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
		if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
			if event is InputEventMouseMotion:
				$Camera_Controller.rotate_y(-event.relative.x * 0.0025)
				cam_2.rotate_x(-event.relative.y * 0.0025)
				cam_2.rotation.x = clamp(cam_2.rotation.x, deg_to_rad(-30), deg_to_rad(60))
				cam.rotate_x(-event.relative.y * 0.0025)
				cam.rotation.x = clamp(cam.rotation.x, deg_to_rad(-30), deg_to_rad(60))

@rpc("call_remote", "any_peer")
func take_damage(amount: int) -> void:
	print(label_3d.text, " health: ",  health)
	health -= amount
	if health <= 0:
		# Handle player death (e.g., respawn, game over)
		print("Player died!")
		$"../".lobby_text_1("End of match. ", %Label3D.text, " lost!")
		print(label_3d.text, " lost! Sword Fight")
		
		
	

func attack() -> void:
	$Camera_Controller/Camera_Target/Camera3D2/sword/CollisionShape3D.rotation_degrees == Vector3(-30, 0, 0)
	$Camera_Controller/Camera_Target/Camera3D2/sword/sword.rotation_degrees = Vector3(-30, 0, 0)
	$Camera_Controller/Camera_Target/Camera3D2/sword/sword.rotation_degrees == Vector3(-30, 0, 0)
	$Camera_Controller/Camera_Target/Camera3D2/sword/CollisionShape3D.rotation_degrees = Vector3(-30, 0, 0)
	

func undo_attack() -> void:
	$Camera_Controller/Camera_Target/Camera3D2/sword/CollisionShape3D.rotation_degrees == Vector3(0, 0, 0)
	$Camera_Controller/Camera_Target/Camera3D2/sword/sword.rotation_degrees = Vector3(0, 0, 0)
	$Camera_Controller/Camera_Target/Camera3D2/sword/sword.rotation_degrees == Vector3(0, 0, 0)
	$Camera_Controller/Camera_Target/Camera3D2/sword/CollisionShape3D.rotation_degrees = Vector3(0, 0, 0)




func get_health() -> float:
	return health

func respawn() -> void:
	Input.action_press("respawn")
	Input.action_release("respawn")


func _on_sword_body_entered(body: player) -> void:
	body.rpc("take_damage", 5) # Call the RPC to the server
	body.take_damage(5)
	
	players_killed += 1
	
	print(%Label3D.text, " Players Killed: ", players_killed)
	
	if players_killed == 0 and multiplayer.get_peers().size() == 0:
		$"../".lobby_text_1("End of match. ", %Label3D.text, " Won!")
	if players_killed == 18 and multiplayer.get_peers().size() == 1:
		$"../".lobby_text_1("End of match. ", %Label3D.text, " Won!")
	if players_killed == 36 and multiplayer.get_peers().size() == 2:
		$"../".lobby_text_1("End of match. ", %Label3D.text, " Won!")
	if players_killed == 54 and multiplayer.get_peers().size() == 3:
		$"../".lobby_text_1("End of match. ", %Label3D.text, " Won!")


# Example with a custom function
func _is_touchscreen() -> float:
	return OS.has_feature("touchscreen")

Lobby nodes:

Player Nodes:

Screenshot 2025-02-14 171015

All the info I have

Do you get any errors when doing this?

No, I dont think I had any errors

Hello?

Setting authority in enter_tree callback has never worked for me, i would devise a different time to set authority usually in a deferred call.

This would require you to rework your ready function for the player.

Do i put it in _ready()

You can but make it deferred.

Ok i know how to do that

Another option is to setup a custom spawn function on a MultiplayerSpawner and set the authority during the spawn.

How to do that

@onready var player_spawner : MultiplayerSpawner = $MultiplayerSpawner
#setup the spawner with the function
func ready() -> void:
	player_spawner.spawn_function = spawn_func

# during peer connection use the spawn function
func _on_peer_connected(id):
	print("peer_connected: ", id)
	player_spawner.spawn(id)

# spawn func takes only one parameter and returns the node to be added to the tree.
func spawn_func(id:int) -> Node :
	var p = player_res.instantiate()
	p.name = str(id)
	p.set_multiplayer_authority(id)
	return p

Thanks I will try

Is this the player script

I kept experementing and then I found out its the problem with the camera