Cannot spawn objects in Multiplayer

Godot Version

v4.2.stable.official [46dc27791]

Question

I’m trying to make a winter-themed multiplayer game where players throw snowballs at each other. The problem is that when one player throws a snowball, the game spawns PackedScene at a Node that the MultiplayerSpawner is tracking to, but only the one who threw it can see it, no one else can. It also throws this error:
get_node: Node not found: "Node3D/Snowballs/snowball3771177691/MultiplayerSynchronization" (relative to "/root").
process_simplify_path: Parameter "node" is null.

I tried literally everything, but nothing worked, including creating a scene from an @rpc function.

Project to debug on: [forum won’t allow Google Drive links for some reason]
You’re able to comment straight from Google Drive, feel free to point out the error directly in file.

Well if Forum does not allow that, i guess i’ll give the important code.
Object spawning code:

@rpc("authority", "reliable", "call_local", 2)
func createSnowball(pos, sped, spedy):
	var scenesic = Game.snowball.instantiate()
	scenesic.set_meta("author", name)
	scenesic.name = "snowball" + str(randi())
	scenesic.position = pos
	rotate_y(rotation.x * .2)
	scenesic.linear_velocity = sped
	scenesic.linear_velocity.y += spedy
	
	Game.map.get_node("Snowballs").add_child(scenesic, true)

Object tree:
image
(MultiSync is set up to sync RigidBody3D, while MultiplayerSpawner’s spawn path is Snowballs (You can see them in the video) and has an object that it cannot spawn in spawn list)

Here’s the video representing this issue:

Hey @Secton,

Two things that I’ve noticed from your setup.

The first is that you are generating a random name for your snowballs. This is generally not a good idea, especially if you’re running the same logic on client and server. The issue is that different peers may generate different IDs ( depending on the RNG’s state ), which means the names will be different, and RPC calls will fail, as they match on node path.

Instead, I’d recommend generating a random ID on the spawning peer, and including that in the RPC call - this way, the snowball will have the same name on all peers.

The other thing is, did you add the snowball scene to the MultiplayerSpawner’s autospawn list? This is something I tend to forget and then bang my head against the wall on why it’s not working :smiley:

Hello!
Thanks for replying, i thought no one will respond to me…

I changed it so that it names the instanced scene as [peer id]snow (the peer id is first to avoid adding +1 to it if it’s not the only one with that id.

I’ve also noticed that i had changed the MultiplayerSpawner’s authority to the player’s one, removed it. Now only Host can spawn objects. Atleast we’re getting somewhere. By the way, now there’s different errors appear (not on host):

Cool, there’s progress :slight_smile:
Of the top of my head, I’d recommend the following:

  • Make sure each peer owns their own player nodes
  • Don’t use MultiplayerSpawner for snowballs, since they are spawned through RPCs ( i.e. you’re trying to synchronize the same thing two different ways )
  • Change the RPC function a bit:
@rpc("authority", "reliable", "call_local", 2)
func createSnowball(id, pos, sped, spedy):
	var scenesic = Game.snowball.instantiate()
	scenesic.set_meta("author", name)

	# Set unique name, consistent on every peer
	scenesic.name = "snowball " + str(id)
	# Set authority to player who threw the ball
	scenesic.set_multiplayer_authority(get_multiplayer_authority())

	scenesic.position = pos
	rotate_y(rotation.x * .2)
	scenesic.linear_velocity = sped
	scenesic.linear_velocity.y += spedy
	
	Game.map.get_node("Snowballs").add_child(scenesic, true)
  • Include random id in call, like rpc("createSnowball", randi(), ...)

Hopefully this will get rid of the node not found errors. I’m rooting for this to be resolved, the game itself looks fun :slight_smile:

Okay, i changed the rpc function. but it still seems to allow creating objects only for host… Well, in this case i guess i can give a project to debug on:
SnowBattle (v4.2.stable.official [46dc27791])
You’re able to comment straight from Google Drive, feel free to point out the error directly in file.

I do apologize for my bad English and for extremely rare use of comments, i rely on my memory :sweat_smile:

Hey @Secton, you forgot to call the RPC as an RPC :slight_smile:

So instead of:

		createSnowball($Camera3D/Weapon/YANode3D/Snow.global_position,
					   $Camera3D.global_transform.basis.z * -20.0,
					   $Camera3D.rotation_degrees.x / 8)

Do this:

		rpc("createSnowball", $Camera3D/Weapon/YANode3D/Snow.global_position,
					   $Camera3D.global_transform.basis.z * -20.0,
					   $Camera3D.rotation_degrees.x / 8)

The parameters are the same, you just specify the RPC’s name first. Since you called it without an RPC, it only ran locally, which resulted in one peer having a snowball, while the other not. This is why the “Node not found” errors popped up. You can read more in the docs here.

Tested it locally with Godot 4.2, both players can throw snowballs.

Also I really like the crouch mechanic!

2 Likes

OH MY GOD FINALLY!!! THANK YOU SOOO MUCH!!! Finally my week of suffering has been finished…

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.