Open riazey opened 1 year ago
cc @Faless
I'm experiencing the same issue when attempting to delete or remove a node (which contains a MultiSync with local as authority, spawned in on local via MultiSpawner) on the server side, with one error message per node deleted. The error messages do not occur on clients connected to the server.
Experiencing a similar issue. Any progress on this?
For nodes that gets dynamically added/removed from tree, you want to use a MultiplayerSpawner
to ensure proper replication across clients. See this article for example.
You can use the visibility API (public_visibility
/set_visibility_for
/is_visible_to
/add_visibility_filter
) to control which player will see and receive updates for a specific node/synchronizer.
Got the same problem here. I think I set up everything correctly:
1) Got the MultiplayerSpawner
in my level, with spawn path to players-container and auto spawn list element 0 to my player.tscn
.
2) In my player.tscn
got a MultiplayerSynchronizer
that synchronizes all my properties with correct visiblity
Getting the same _getnode: Node not found [...]Player/1/MultiplayerSynchronizer error.
After some debugging I found out what happens in my project: The host correctly gets spawned in (Player 1) on his side. Then when the first client joins (Player 2), on the host-side the client player gets correctly spawned (host now has: Player 1 & Player 2 nodes). But on the client side, only the client Player get spawned in, but not the host player (so client now only has Player 2 node), which means the client throws an error that Player 1 (the Player 1 node or more precisely it's MultiplayerSynchronizer) is missing...
Am I doing something wrong here? I think I followed the tutorial and setup correctly... I can also share my project over a call if somebody wanna take a look with me
What you are all likely missing is configuring your MultiplayerSpawner's Auto Spawn List to include your player scene, so that when a client joins, the host's player scene is spawned automatically and its MultiplayerSynchronizer node is in your node tree.
I'm having the same problem, but I'm using RPC calls to spawn a node in both client and server. Idk if it's relevant but I'm adding a scene into MultiplayerSpawner and instantiating an inherithed scene
For nodes that gets dynamically added/removed from tree, you want to use a
MultiplayerSpawner
to ensure proper replication across clients. See this article for example.
Maybe it's not the ideal place to ask, but that article is adding the authority in getset. This seems to be forbidden in latest dev5. The tutorial adds auth like this:
# Set by the authority, synchronized on spawn.
@export var player := 1 :
set(id):
player = id
# Give authority over the player input to the appropriate peer.
$PlayerInput.set_multiplayer_authority(id)
I tried to do the same in c#
public int _clientId;
public int clientId {
get { return _clientId; }
set {
_clientId = value;
GD.Print("SETTER > setmultiplayerauthority");
SetMultiplayerAuthority(value);
}
}
I set clientId just before adding it in the tree, and this is what I get in console.
"/root/Game/ServerStore/Beach/Players/Player2/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()
Shall I create a github issue for this?
What you are all likely missing is configuring your MultiplayerSpawner's Auto Spawn List to include your player scene, so that when a client joins, the host's player scene is spawned automatically and its MultiplayerSynchronizer node is in your node tree.
Not in my case. The spawner is populated with the player scene.
My strategy is:
Both map and player are inside the Multiplayerspawner
The server:
The client:
This is the remote window from client:
And this is remote tree from server:
It gets fixed if you disable the "Public Visibility" of the NetworkSynchroniser located inside each player, which will make the props not to sync.
My guess is that is accurate that the "Map" is not loaded when the sync starts. So I might need to set Public visibility to off and find a way to tell players that only the players inside that map should be able to sync variables (if I understand it correctly)
I will try to set the visibility manually only when the scene is completely loaded as this comment recommends and see if that helps
After tinkering a little bit I arrived into the following rule of thumb:
This apparently works well! But I guess for more performative and non prototype projects you should use low level network
But this looks much more like a Server-Client model than a P2P where every player is responsible for its own scenes... Maybe I'm still missing something
But my rule solves this issue problem
Basically you want something similar to this:
@rpc("any_peer", "call_local", "reliable")
func add_node(nodePath: String):
if not multiplayer.is_server():
return
# Always send the nodePath
var newNode = load(nodePath).instantiate()
# Here is the MultiplayerSpawner Spawn Path
# Don't forget this "true" in add child
get_node("/root/Game/Level").add_child(newNode, true)
@rpc("any_peer", "call_local", "reliable")
func remove_node(nodePath: String):
if not multiplayer.is_server():
return
# Here you MUST receive a node path!
var e = get_node(nodePath)
if e:
e.queue_free()
When calling from server or client you can use
remove_node.rpc("res://your_node")
add_node.rpc("res://your_node")
# or
remove_node.rpc(yourNode.get_path())
add_node.rpc(yourNode.get_path())
Just as another note in case someone ends up here, the issue I ran into to cause something like this was accidentally calling add_child
on the wrong node. E.g. if you have your players in a node in your scene called 'players' make sure when you add them to the scene you're not adding them somewhere other than what is listed as the spawn path in the MultliplayerSpawner. An obvious issue but easy to miss if you're new to godot's networking
Either if I use RPCs or a predefined spawner, and am not missing the parent node, I can confirm this error. Adding a multiplayer synchronizer to dynamically spawned objects will cause this error on despawn. Everything works as intended, but why this error set is shown in client in each despawn? Something is really of here, and I feel that there is some unexpected thing happening. I kind of confirm this problem too... but am also new to godot....
I had the same issue while trying to fiddle around the project mentionned in the above comments (https://github.com/godotengine/tps-demo)
Succinctly, I tried to split the UI node from the menu
scene in a loading, setting and login scene. Login hold the loading scene, hidden by default. The loading scene is generalist: it holds functions to load any resource and update itself with a loading bar while waiting for the ResourceLoader, and finally emit a signal when done. Its code is as follow:
var path = "res://scenes/world_screen/world_screen.tscn"
signal loaded(path: String)
@onready var loading_progress = %Progress
@onready var loading_done_timer = %DoneTimer
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta):
if visible:
var progress = []
var status = ResourceLoader.load_threaded_get_status(path, progress)
if status == ResourceLoader.THREAD_LOAD_IN_PROGRESS:
loading_progress.value = progress[0] * 100
elif status == ResourceLoader.THREAD_LOAD_LOADED:
loading_progress.value = 100
set_process(false)
loading_done_timer.start()
else:
print("Error while loading level: " + str(status))
hide()
func _load(new_path: String, cb: Callable, sub_thread: bool = true):
show()
path = new_path
loaded.connect(cb)
if ResourceLoader.has_cached(path):
loaded.emit()
else:
ResourceLoader.load_threaded_request(path, "", sub_thread)
func _on_done_timer_timeout():
loaded.emit(path)
Running it however throws the following set of errors:
This error do not happen if I do not use the loading
scene and directly perform the load_threaded_request
in the login
scene.
There is a comprehensive way to do it? I never found a correct way of using godot multiplayer
There is a comprehensive way to do it? I never found a correct way of using godot multiplayer
@olivatooo There is a comprehensive guide on how to spawn level and players here: https://godotengine.org/article/multiplayer-in-godot-4-0-scene-replication/
@banane42 I can't really tell what's happening, make sure you are not removing the level yourself, or try to make an MRP and open a new issue.
Reproduced using v4.2.2.rc.custom_build [474589eb8]
@Faless
@banane42 I can't really tell what's happening, make sure you are not removing the level yourself, or try to make an MRP and open a new issue.
Removed my earlier comment as I discovered I'm an idiot and was removing the level on the connecting client via a signal.
I ran into the original issue, where a spawned player's MultiplayerSynchronizer was not found when other clients connected. My setup, really for experimenting, was to build a dedicated server, have the server auto-spawn a dummy player, so when clients join they can see them.
However, I was adding the player object (to be spawned) during the server's game_manager
ready function, which led to this error because the scene was not ready to add a player. At least that's what I think is happening, because once I added a 3 second timer after the ready was hit, the dummy player was added to the scene as expected, and all clients had it spawned properly.
Maybe there is a bug as this is a slightly different use case, but it's likely something that's expected to be there, some node, isn't.
I have the same issue, but the only twist is that it works where I am on the same computer, like running multiple instances of the game on the same machine. But when I open the game on two or more computers, the server computer will run into this issue. I don't know what happen at this point.
Godot version
4.0.2
System information
Windows 10
Issue description
For nodes with a MultiplayerSynchronizer child:
Originally I had planned to only instance scenes on a client if they were in the same "area" but maybe I am barking up the wrong tree~? >0<
Steps to reproduce
OR
OR
Minimal reproduction project
Note: GUI script has a bool/toggle for deleting a node with a MultiSyncy on it after joining
Multiplayer_Test.zip