godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.1k stars 21.15k forks source link

MultiplayerSynchronizer shares config after copying #74381

Open sygi opened 1 year ago

sygi commented 1 year ago

Godot version

4.0-stable

System information

Ubuntu 22.04

Issue description

When a Node tree including a MultiplayerSynchronizer is copied, only the reference to the underlying replication_config is recreated. This leads to an unintuitive behavior: while the two MultiplayerSynchronizers look like separate nodes, they share their configuration, which is not explicitly accessible from the editor's UI.

Instead, one of the following should happen:

  1. The UI having explicit access to the replication config, with the user being able to create a new one in the place of the previous one, or
  2. when copying the synchronizer, the replication config also should be copied and each instance using their own config from now on.

Steps to reproduce

  1. Create a node tree with a MultiplayerSynchronizer, eg:

    Sprite2D
    + MultiplayerSynchronizer
  2. Duplicate the node via ctrl-D in the editor.

  3. You will end up with the scene file along the lines:

    
    [node name="Sprite2D" type="Sprite2D" parent="."]

[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="Sprite2D"] replication_config = SubResource("SceneReplicationConfig_00844")

[node name="Sprite2D2" type="Sprite2D" parent="."]

[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="Sprite2D2"] replication_config = SubResource("SceneReplicationConfig_00844")



### Minimal reproduction project

Reproduction is trivial.
akien-mga commented 1 year ago

I don't know how problematic this in the context of MultiplayerSynchronizer specifically, but generally this is Godot's standard and expected behavior. Resources are shared by default, and if you need to make them unique you can use the "Make Subresources Unique" option.

Think for example of a Sprite2D using a texture. If you create 100 copies of the Sprite2D, they will also share the same texture resource. That's much better for memory usage.

sygi commented 1 year ago

That makes sense but note that the behavior is different for Sprite2D: it's like in the case 1 above: the texture is explicitly referenced as a property in the UI of Sprite2D node. To edit it, you need to go to the resource, which makes it clear that these are two separate entities. Compare that with MultiplayerSynchronizer:

synchronizer ui

there is no explicit information about the config, the user just clicks on the the MS and modifies its behavior via the "Replication" tab with no indication that the entity being changed is not MS itself but rather its implicit (and potentially shared) config.

jjolmo commented 1 month ago

Happens to me in my current hierarchy.

I have a scene called "Creature". Then I have a "Monster" scene which is inherited from "creature". I want the replication in monster to inherit but include new functions, or even remove some of them. But they share config. You can make them unique from the editor: image

but there's no clue of what is happening, what is inheriting, or if it contains a unique resource. I would expect to display a "Replication config" section which lets you make it unique, save, and load, the same way you can do it with any other resource like colliders, sprite libs etc. Otherwise it isn't very clear to use this tool.

As a workaround, when inheriting, I'm just creating a new "MPSync" node instead of making it unique then edit the config. It just makes things easier to understand via the interface. Still this does not solve the possibility to mutate/change variables from the inherited without affecting the parent config,

I would expect this config to behave more like in a godot-ish style with a resource