Host/Client Desync on Spawn

Godot Version

GodotSteam 4.6.2

Question

Currently I’m able to have players spawn in to my level from a pregame lobby, which collects info such as steam name, creates/stores peer ID, etc. in a global script. However, on spawning into the level, the host and client are not synchronized. The client cannot see the host at all, and the host can’t see the client moving. Can I have some help diagnosing where that issue is coming from? Previously I didn’t have this problem, and am not sure how it popped up. Error messages are indicating the client thinks the host node doesn’t exist

Scene tree below. The way it works is:

  1. RiverLevel is instantiated and spawned with MultiplayerSpawner node. No issues here as far as I can tell, as objects in the level seem to sync perfectly between host and clients.

  2. Upon level load, the LevelLoader node and its script (below) fires its ready function, which triggers the host to spawn, and gets the clients to rpc the host when they’ve loaded the scene.

  3. Host receives rpc with the client’s peer id, and uses it to spawn their character and assign authority to that peer id

extends Node3D

#1) Drop into level scene under root node
#2) Make local and assign nodes to export vars

#LEVEL_LOADER SCRIPT

@export var player_container: Node3D 
@export var level_gametype_header: Label 
@export var player_spawner: MultiplayerSpawner

func _ready() -> void:
	level_gametype_header.show()
	await get_tree().create_timer(4.75).timeout
	level_gametype_header.queue_free()
	await get_tree().create_timer(.25).timeout
	spawncommand()

@rpc("any_peer","call_remote","reliable") #any peer can call this RPC, but it won't be performed locally: only remotely (on the host), reliably
func client_ready_notify():
	var client = multiplayer.get_remote_sender_id()
	print(str(client) + " fired client_ready_notify rpc")
	
	if !multiplayer.is_server(): return
	if multiplayer.is_server():
		await get_tree().create_timer(5).timeout
		player_spawner.spawnplayers_v2(client)

func spawncommand():
	if multiplayer.is_server(): 
		player_spawner.spawnplayers_v2(1) #spawn the host
	if !multiplayer.is_server():
		client_ready_notify.rpc_id(1) #rpc the host with the clients peerid. have the host spawn that client
#PLAYER SPAWNER SCRIPT
extends MultiplayerSpawner

@onready var Caveman: PackedScene = preload("res://Scenes/Player/Caveman_v2.tscn")
@onready var PlayerContainer = $"../PlayerContainer"

func spawnplayers_v2(peer_id): #spawns players once they load the scene and rpc the host they're ready - accounts for late joiners/slow loaders, and those there at start. Called by level_loader script by host
	for i in Global.LOBBY_MEMBERS.size(): #for each dictionary within the total # of dictionaries in the array
		if Global.LOBBY_MEMBERS[i].peer_id == peer_id: #if dictionary "x" has a peerid value = to that which is fed into the func, match it with its relevant player info
			var steam_name = Global.LOBBY_MEMBERS[i].steam_name
			var steamid = Global.LOBBY_MEMBERS[i].steam_id 
			var team = Global.LOBBY_MEMBERS[i].team
			

			var Cavemanins = Caveman.instantiate() 
			Cavemanins.name = str(peer_id)
			Cavemanins.set_multiplayer_authority(peer_id) 
			PlayerContainer.add_child(Cavemanins) #no luck using call deferred

			await get_tree().process_frame
			player_position_setter.rpc(peer_id, team)

(The errors received on the client’s end)

When adding syncrhonized children use the force_readable_name option, otherwise the .name based on peer id may be discarded.

PlayerContainer.add_child(Cavemanins, true)

Your many uses of await are pretty scary too,