MultiplayerSynchronizer synchronises all peers. Host can move on host game, but movement not shown on peers

Godot Version

Question


func spawn_player(peer_id:int):	
	var p:Player = PLAYER.instantiate()	
	
	p.name = "player-%s"%str(peer_id)	
	p.peer_id = peer_id
	
	p.multiplayer_synchronizer.set_multiplayer_authority(peer_id)
	p.set_multiplayer_authority(peer_id)
	
	return p

Peers can all see each-other move. Host can move, but peers cannot see him move. They are all handed authority as you see here.

It is a custom spawner:

func _enter_tree() -> void:
	multiplayer_spawner.spawn_function = spawn_player

Spawned like so:

multiplayer_spawner.spawn(peer_id)

I can’t for the life of me figure out why the host (id #1) is seen as a special stubborn case here.

I really like this approach! I tested it locally and didn’t have an issue with the host player.

Maybe there is some code in the player that is blocking updates.

FYI, set_multiplayer_authority is recursive. You only technically need to set it once on the player node and all children will be authed. If you don’t want all child nodes authed there is a function params you can set to not do that.

Maybe it’s because I’m using beta version of 4.3. I’ll check on what you said and get back to you.

You can inspect nodes in the remote scene tree. And to switch between the peers click on the different debug panes in the editor.

The problem was completely unrelated to bugs. I had a few issues upstream (my fault). Thanks!

Hey, I’m having a similar problem, if you don’t mind me asking, what was your issue?

I was running spawn code too early, and the synchronization was occurring before the connection was complete (I think).

I mistake was as follows. I ran spawning code directly after this:

func join_game(address = "", port = ""):
	if address.is_empty():
		address = DEFAULT_SERVER_IP
	if port.is_empty():
		port = PORT
	var peer = ENetMultiplayerPeer.new()
	var error = peer.create_client(address, int(PORT))
	if error:
		return error
	multiplayer.multiplayer_peer = peer

Things did not cooperate until I moved my spawning code into this process:

multiplayer.connected_to_server.connect(_on_connected_ok)

Running the spawn logic after the “_on_connected_ok” made it safe and everything functioned as desired.

Whereas before I was launching a level directly after joining, and the level would do a “level ready” callback that would spawn the character…giving me much grief.

If you are having the same problem, let me know what your fix ends up being.

1 Like

Ah, alright. Unfortunately, I believe I am having a different issue. However, I might try incorporating a similar concept. Thanks for the response!

Hey, I actually found a solution to my problem, since you asked. Here’s what the problem was:

Like what your issue, I was adding the peers before the host. Except I was changing scenes instead of handling connections.

So, what I did was I created a signal called readyforpeerspawn, then, when I called my sync_peers function (the one that would instantiate the players), I would check if the current client was the host using if_server (I’m not sure this would be necessary if you’re not operating on peer to peer), adding the host and peers to the new level, emitting the previously created signal. If the client wasn’t the host, it would await the signal which the host emits, then add the host and peers on the client side.

Here’s the code:

const Player = preload("res://player.tscn")

@onready var _spawner = $MultiplayerSpawner

signal readyforpeerspawn

func _ready():
	sync_peers.rpc()

@rpc("call_local")
func sync_peers():
	var players = multiplayer.get_peers()
	
	if multiplayer.is_server():
		add_player(multiplayer.get_unique_id())
		for peer in players:
			add_player(peer)
			print(peer)
			readyforpeerspawn.emit()
	else:
		await readyforpeerspawn
		add_player(multiplayer.get_unique_id())
		for peer in players:
			add_player(peer)
			print(peer)

func add_player(peer_id):
	var player = Player.instantiate()
	player.name = str(peer_id)
	add_child(player)

I really appreciate your response, as it actually really helped me solve this, despite being a slightly different issue! I’m not sure this code will help you, since you said you already fixed your problem (and I’m not sure if my implementation is the best, lol). But, if anybody else stumbles upon this post, I hope this can be of assistance, even if it’s just diagnosing the issue.