Description
Tested versions
4.3 release (not C#)
System information
Godot v4.3.stable.mono - Windows 10.0.22631 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3090 (NVIDIA; 32.0.15.6094) - AMD Ryzen 9 5900X 12-Core Processor (24 Threads)
Issue description
Hopefully this issue is a nice break from the others, it's kind of like a reverse-bug where an error is thrown, but the correct behavior is observed.
I'm following an implementation pattern similar to this blog post: https://godotengine.org/article/multiplayer-in-godot-4-0-scene-replication/
Essentially, when a Node is spawned, and the multiplayer authority of a child MultiplayerSynchronizer node is changed during _ready() or _enter_tree(), this error is thrown:
E 0:00:06:0613 on_replication_start: The MultiplayerSynchronizer at path "/root/Lobby/Spawns/676522849/MultiplayerSynchronizer" is unable to process the pending spawn since it has no network ID. This might happen when changing the multiplayer authority during the "_ready" callback. Make sure to only change the authority of multiplayer synchronizers during "_enter_tree" or the "_spawn_custom" callback of their multiplayer spawner.
<C++ Error> Condition "pending_sync_net_ids.is_empty()" is true. Returning: ERR_INVALID_DATA
<C++ Source> modules/multiplayer/scene_replication_interface.cpp:243 @ on_replication_start()
But if the node is inspected in the remote scene trees, the correct multiplayer authority is displayed for all clients. The error is repeated again when a new client joins, for every current client. (i.e. first client join sees 1 error, second client join is 4 total errors, third client brings the total to 9, ...)
The error is NOT thrown if a base Node is used instead of a MultiplayerSynchronizer - so I'm worried there may still be something behind the error going wrong I'm not aware of.
I've also tried adding a timed delay after the player joins, and the player node is instantiated, but before it is added to the scene by parenting to the Spawn node - so I believe this is unrelated to spawning a player node too soon after a player connects.
Steps to reproduce
I've created a micro example if anyone wants to try, you only need to make two scenes:
Lobby.tscn (default start scene)
- Add MultiplayerSynchronizer as child of this Node
- Add Node as child, name it Spawns
- Add the following script to the Lobby:
extends Node
@onready var spawns: Node = $Spawns
@onready var spawner: Node = $MultiplayerSpawner
const PORT = 7000
const DEFAULT_SERVER_IP = "127.0.0.1"
var Player = preload("res://player.tscn")
func _ready() -> void:
spawner.spawn_path = spawns.get_path()
spawner.add_spawnable_scene("res://player.tscn")
create_buttons()
func create_game():
print('Creating Game')
var peer = ENetMultiplayerPeer.new()
peer.create_server(PORT)
multiplayer.multiplayer_peer = peer
multiplayer.peer_connected.connect(add_player)
func join_game():
print('Joining Game')
var peer = ENetMultiplayerPeer.new()
peer.create_client(DEFAULT_SERVER_IP, PORT)
multiplayer.multiplayer_peer = peer
func add_player(peer_id):
print('Adding Player, Peer ID: %s' % [str(peer_id)])
# await get_tree().create_timer(2.0).timeout
# print('Timeout Done')
var player = Player.instantiate()
player.name = str(peer_id)
spawns.add_child(player, true)
func create_buttons():
var vbox = VBoxContainer.new()
add_child(vbox)
var host_button = Button.new()
host_button.text = "HOST"
host_button.connect("pressed", create_game)
vbox.add_child(host_button)
var join_button = Button.new()
join_button.text = "JOIN"
join_button.connect("pressed", join_game)
vbox.add_child(join_button)
player.tscn
- Add MultiplayerSynchronizer as child
- Add this script to the MultiplayerSynchronizer:
extends MultiplayerSynchronizer
func _enter_tree() -> void:
print("NetID: %s is setting multiplayer authority to %s" % [str(multiplayer.get_unique_id()), str(get_parent().name)])
set_multiplayer_authority(get_parent().name.to_int())
print("NetID: %s sees authority: %s" % [str(multiplayer.get_unique_id()), str(get_multiplayer_authority())])
Now to test it, you should see an error like:
E 0:00:06:0613 on_replication_start: The MultiplayerSynchronizer at path "/root/Lobby/Spawns/676522849/MultiplayerSynchronizer" is unable to process the pending spawn since it has no network ID. This might happen when changing the multiplayer authority during the "_ready" callback. Make sure to only change the authority of multiplayer synchronizers during "_enter_tree" or the "_spawn_custom" callback of their multiplayer spawner.
<C++ Error> Condition "pending_sync_net_ids.is_empty()" is true. Returning: ERR_INVALID_DATA
<C++ Source> modules/multiplayer/scene_replication_interface.cpp:243 @ on_replication_start()
and output in the terminal like:
Creating Game
Joining Game
Adding Player, Peer ID: 622658096
NetID: 1 is setting multiplayer authority to 622658096
NetID: 1 sees authority: 622658096
NetID: 622658096 is setting multiplayer authority to 622658096
NetID: 622658096 sees authority: 622658096
And if you inspect the MultiplayerSynchronizer node in the Scene -> Remote panel, both sessions will show the correct authority.