Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behaviour with MultiplayerSpawner after changing scenes (with change_scene_to_*) via RPC call #68407

Open
mitchelljeffery opened this issue Nov 8, 2022 · 21 comments

Comments

@mitchelljeffery
Copy link

mitchelljeffery commented Nov 8, 2022

Important

 Bugsquad note: This issue has been confirmed several times already. No need to confirm it further.
Please read #68407 (comment) for a workaround.

Godot version

4.0.beta4

System information

Windows 11 22H2

Issue description

I've setup a simple lobby which will only load both players into another scene once a client connects to the host. After the scene is loaded some subscenes are instantiated on the host and added to a child node in the scene.

What I expect to happen is, the MultiplayerSpawner will spawn the subscenes on the client at the position (0, 0). However it seems that because I am using an rpc call to load the scene for both the host(locally) and client(remotely) the MultiplayerSpawner fails. The code block below is what the debugger returns for the client instance.

E 0:00:02:0861   get_node: Node not found: "Main/MultiplayerSpawner" (relative to "/root").
  <C++ Error>    Method/function failed. Returning: nullptr
  <C++ Source>   scene/main/node.cpp:1359 @ get_node()
E 0:00:02:0861   process_simplify_path: Condition "node == nullptr" is true.
  <C++ Source>   modules/multiplayer/scene_cache_interface.cpp:77 @ process_simplify_path()
E 0:00:02:0861   get_cached_object: ID 2 not found in cache of peer 1.
  <C++ Error>    Condition "!F" is true. Returning: nullptr
  <C++ Source>   modules/multiplayer/scene_cache_interface.cpp:249 @ get_cached_object()
E 0:00:02:0861   on_spawn_receive: Condition "!spawner" is true. Returning: ERR_DOES_NOT_EXIST
  <C++ Source>   modules/multiplayer/scene_replication_interface.cpp:484 @ on_spawn_receive()

The MultiplayerSpawner does sometimes produce the expected results, albeit very infrequently. What baffles me is that I've had a friend test this on their own machine with the same release of Godot and the MultiplayerSpawner seems to work as expected.

I've found that the MultiplayerSpawner behaves as expected if I load the scene manaully for each instance, rather than through an rpc call for both the host(locally) and client(remotely).

Steps to reproduce

To test loading via RPC

  1. Set the project to run with 2 instances
  2. Run Project
  3. Select host for one instance and join for the other

To test loading manually

  1. Set the project to run with 2 instances
  2. Uncomment start_game() on line 12 and 26 in lobby.gd
  3. Run Project
  4. Select host for one instance and join for the other

Minimal reproduction project

multiplayer-nodes.zip

@Chaosus Chaosus added this to the 4.0 milestone Nov 8, 2022
@Chaosus Chaosus moved this to To Assess in 4.x Priority Issues Nov 8, 2022
@Chaosus Chaosus moved this from To Assess to Todo in 4.x Priority Issues Nov 8, 2022
@Roupp
Copy link

Roupp commented Dec 6, 2022

I'm experiencing the same problem as I tried to add MultiplayerSpawner to my project, where I use get_tree().change_scene_to_file() method to change between lobby and the gameworld scenes.

In my another demo project the MultiplayerSpawner works fine when everything is contained under one node and I don't change scenes with that method.

Godot version
4.0.beta6

System information
Windows 11 21H2

I would love a fix or workaround to this problem.

@Cretezy
Copy link
Contributor

Cretezy commented Dec 16, 2022

I'm also experiencing the same issue (beta8/master). I have 2 cases in my testing game:

  1. One instance creates a server, another instance connects to the server, they are in a lobby. The server starts the game, which adds the World with the MultiplayerSpawner to both the instances, then spawns the Players (which are synced with the MultiplayerSpawner). This works as intended.
  2. One instance creates a server and starts the game, another instance connects to the server. In this case, the client is instructed to add the World (same as the scenario above), however this doesn't work.

I can actually replicate the issue of 2. on 1. by adding World on the client after spawning the Players. This does match the behavior of 2.

From what I can tell: The MultiplayerSpawner doesn't work on the client if it's added after children are already spawned.

@Cretezy
Copy link
Contributor

Cretezy commented Dec 17, 2022

I've found another case where this can happen.

If the client has a World scene and the server has a ServerWorld scene which is inherited from World, the MultiplayerSpawner does not work (same error as the OP).

@baptr
Copy link
Contributor

baptr commented Feb 17, 2023

I fought with what I think is the same underlying problem as OP (at least) last week.

As I understand it (take with a grain of salt), the replication interface does some work to map node path strings down to IDs to optimize future communication between the peers. Unfortunately, this "simplify_path" operation seems to ~only happen when a peer first connects. If the client hasn't loaded the to-be-synced tree yet when the connection is established, you get:

E 0:00:05:0038   get_node: Node not found: "Main/MultiplayerSpawner" (relative to "/root").
  <C++ Error>    Method/function failed. Returning: nullptr
  <C++ Source>   scene/main/node.cpp:1364 @ get_node()
E 0:00:05:0038   process_simplify_path: Condition "node == nullptr" is true.
  <C++ Source>   modules/multiplayer/scene_cache_interface.cpp:77 @ process_simplify_path()

Then, when decoding the server's spawn state, the client can't use the simplified node identifier (since it wasn't able to establish it, and may still not have the node in the tree). Thus, you get these for each to-be-spawned object :

E 0:00:05:0038   get_cached_object: ID 2 not found in cache of peer 1.
  <C++ Error>    Condition "!F" is true. Returning: nullptr
  <C++ Source>   modules/multiplayer/scene_cache_interface.cpp:241 @ get_cached_object()
E 0:00:05:0038   on_spawn_receive: Condition "!spawner" is true. Returning: ERR_DOES_NOT_EXIST
  <C++ Source>   modules/multiplayer/scene_replication_interface.cpp:567 @ on_spawn_receive()

In my project, I've hacked around this for now by doing a two-phase start. As long as the client scene loads before the server's MultiplayerSpawner notices the peer has connected, they're able to get the paths simplified on that first sync attempt, and everything is golden after that.

@baptr
Copy link
Contributor

baptr commented Feb 17, 2023

Ah, more precisely, it's adding the spawnable nodes in the server's _ready (since the client is already connected, if not loaded) that triggers the sync.

@Faless
Copy link
Collaborator

Faless commented Feb 27, 2023

I tried to figure out a good solution for this issue, but it will need to be pushed for 4.1.

The problem relies on the deferred nature of change_scene_to_*, and would require the multiplayer API to temporarily stop processing packets, waiting until the scene has changed (which requires extra signals from SceneTree).

I would discourage from using change_scene_to_* during a multiplayer session until we address this properly and use a MultiplayerSpawner instead as explained in this blog post.

@Faless Faless modified the milestones: 4.0, 4.1 Feb 27, 2023
@trennepohl

This comment was marked as duplicate.

@sygi

This comment was marked as duplicate.

@PierceLBrooks

This comment was marked as off-topic.

@yrucrem

This comment was marked as duplicate.

@YuriSizov YuriSizov modified the milestones: 4.2, 4.3 Nov 15, 2023
@xzirox

This comment was marked as duplicate.

@Faless

This comment was marked as duplicate.

@xzirox

This comment was marked as duplicate.

@zedrun00

This comment was marked as duplicate.

@vishal-ahirwar

This comment was marked as duplicate.

@g0rski

This comment was marked as duplicate.

@Faless

This comment was marked as duplicate.

@KoBeWi KoBeWi removed this from the 4.3 milestone Aug 3, 2024
@jairodealmeida

This comment was marked as duplicate.

@Faless
Copy link
Collaborator

Faless commented Sep 5, 2024

This issue is confirmed, please do not comment to confirm it further.

The problem relies on the deferred nature of change_scene_to_*, and would require the multiplayer API to temporarily stop processing packets or implement some form of scene reconciliation process.

Please do not use change_scene_to_* during a multiplayer session until this issue is addressed properly, use a MultiplayerSpawner instead as explained in this blog post.

@jairodealmeida

This comment was marked as off-topic.

@adamscott

This comment was marked as resolved.

@adamscott adamscott changed the title Unexpected behaviour with MultiplayerSpawner after changing scenes via RPC call Unexpected behaviour with MultiplayerSpawner after changing scenes (with change_scene_to_*) via RPC call Sep 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests