Nested MultiplayerSynchronizer not working

Godot Version

4.4

Question

I have the following scene tree:

It consists of:
2 MultiplayerSynchronizers:

  • PlayerSynchronizer - synchronizes properties on my players
  • BallSynchronizer - synchronizes properties on balls that players throw

2 MultiplayerSpawners:

  • PlayerSpawner - spawns players
  • ObjectSpawner - spawns balls

2 Nodes that spawned scenes get added to

  • Players - inside of world, contains players

  • Objects - inside of each player, contains balls

  • Spawning works for players and balls.

  • Synchronizing works for players. It does not work for balls.

Multiplayer authority is set on the players, so I assume that should be inherited by the balls that are descendants of players. The only thing I see that is different between my synchronizers is that the one that doesn’t work is nested.

Any help would be much appreciated.

What properties are synchronized on each one?

For the ball, the simplest thing I tried was with a basic Node3D and targeted the position property.

Is it position or global_position that you’re synching on the balls? TBH I don’t think this has anything to do with multiplayer. I think that this has to do with your tree structure. You’re adding the ball as a child of a Node - which has no positional data. position is a value that is in relation to its parent. It has none because its parent is something without that data.

TBH I don’t know exactly what’s going on, but there’s a few things you can try, in the order I think you should try them.

1.) Make your ball a child of World which is a Node3D. It will likely start moving and updating.
2.) Synch - and update in _physics_process() - the ball’s global_position.
3.) Convert the Players, 406675 and Objects nodes to Node3D. Your ball will likely start moving, and will also likely be tied to movement of all the nodes in its tree. (Probably will create its own issues down the line - like that Input node add velocity to your ball when the player moves.)

In general you should also consider not having any Node objects in your tree that have child nodes that are not Node object themselves. For example, there’s no problem having your Input node be a Node object, because it doesn’t have to be anywhere, and neither does anything below it. Something that looks more like this (even though this is Node2D and Node objects) will make your organization clearer, and avoid positional data issues.

1 Like

I also suspect the tree structure may be at play, but I don’t think it’s related to using Node at all. My players move just fine and use the same pattern. I believe position just ends up being relative to next Node3D up the tree (I could be wrong on this point, but regardless I don’t think it is the primary issue).

Another thing to mention is I tried a custom getter setter Vector3 prop and set a breakpoint in the setter. It never gets hit, so it seems the synchronizer never attempts to update the property at all. So it’s not primarily a problem of the ball not moving, it’s that the property never gets set.

If I can solve the property getting set, I should be able to confirm any issues with the actual movement.

Your suggestion to move the ball higher in the hierarchy is a good one. I wonder if the nested structure is somehow to blame

1 Like

I suggested this, and used that screenshot, because an earlier version in another game had Area2Ds hanging off of those State nodes which were inherited from Node They just never triggered. It was like they didn’t exist. I had to create a new State2D inherited from Node2D and then the Area2D nodes started detecting collisions again. It was a problem only on my enemies and not my player, (because my player didn’t need those Areas to react to the environment, player input did that).

This turned out to be an issue with the ball not having multiplayer authority set. I was expecting them to inherit this from the player, but for whatever reason that doesn’t seem to be the case. I ended up encoding the peer id in the ball’s node name as the player is instantiating it and then parsing it out in _enter_tree of my ball scene and setting multiplayer authority there.

1 Like

My new scene tree now looks like this where the ball names contain the peer id (which is also the player name). These then get parsed on scene tree enter to set the multiplayer authority.

I may look at using a custom spawn_function so that I don’t have to encode this in the name. It works fine, just feels a little hacky.

func _enter_tree():
	set_multiplayer_authority(name.split("_")[0].to_int())
1 Like