Skip to content

MultiplayerSynchronizers with shared root_nodes can conflict when setting multiplayer authority #105117

Open
@pierrefranklin

Description

@pierrefranklin

Tested versions

  • Tested in v4.4.stable.mono.official [4c311cb]
  • Tested in v4.0.4.stable.official [fc0b241]

System information

Godot v4.4.stable.mono - Windows 11 (build 26100) - Multi-window, 2 monitors - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1070 (NVIDIA; 31.0.15.4617) - AMD Ryzen 7 3700X 8-Core Processor (16 threads)

Issue description

When using two synchronizers sharing the same root_node, if one sets the multiplayer authority for the first synchronizer it can cause the second to fail to run properly (with an error message). It's unclear to me if this is undefined behavior or not. Specifically, if synchronizer A comes first in the scene tree, and synchronizer B sets a variable that changes synchronizer A's multiplayer authority, and both share the same root_node, the setup fails to correctly set the synchronized variables and the multiplayer authority.

There are two simple workarounds:

  • Set the root node for the modified-authority Synchronizer to itself, instead of the same root node as the other (which I think is the intended structuring anyway)
  • Reorder the nodes so that the modified-authority Synchronizer comes second

I think it's likely I'm doing something not intended for the Synchronizers, however I wasn't able to find any documentation related to this, nor did the error message indicate either of the two solutions I listed above.

Steps to reproduce

In the project attached, run two instances so that one can be host and the other as client (I exported the project and ran two instances of the .exe). There are three rows, with the top one showing the issue, and the bottom 2 showing the workarounds. The "players" consist of two boxes, indicating the spacebar status of each player (their multiplayer id's can be see on the top of the box) according to the server and according to the local state, respectively. Pressing space should send a input to the server which lights the appropriate player's indicators.

The top row will not work for any of the clients (the server player will work). The bottom two rows work and show the two workarounds

To describe the exact setup and problem:

The "Player" scene has two synchronizer children, one for input and one for server state. These are set up almost identically to this blog post, with the exception that the root node of InputSynchronizer is set to the Player root, instead of the InputSynchronizer. This causes the following error message from here:

ERROR: The MultiplayerSynchronizer at path "/root/MultiplayerRoot/Level/PlayerDisplays/PlayersNotworking/1329961786/ServerSynchronizer" 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.

In the code, the server synchronizer controls the Player.player variable which is used to set the multiplayer authority of the InputSynchronizer. The players are spawned by the server, which are replicated for the clients by the MultiplayerSpawner in the player_displays scene.

this blog post
You can also reproduce the error on the original blog post project by ordering the InputSynchronizer before the ServerSynchronizer and changing the root node for the InputSync to be the Player (you will also need to change the property paths in the scene replication tab by deleting and replacing them).

I'm not entirely sure what the root of this would be: initially I thought the order of the synchronizers matters, since the server synchronizer effectively "sets" the multiplayer and so a mismatch of construction/synchronization something something not initialized (I'm not very familiar with the internals of this stuff). However, since changing the root node fixes the issue as well, I assume it's some interaction between the synchronizers on their root node.

Minimal reproduction project (MRP)

synchronizerproblem.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    For team assessment

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions