Destroying an object in multiplayer

Godot Version

v4.1.3

Question

I’m working on my first multiplayer project, and I want the player to be able to pick up an object by removing it from the world and then adding it to their inventory. A text hint will show up in the UI to tell the player that this item can be picked up.

With my current code, when the player interacts with the object, it’s obviously only destroyed on their end and not for anyone else. I don’t know how to make it destroy itself for every player.
Also, the label that is supposed to display text when the player is looking at the object displays the default text at all times. When it starts displaying the hinttext, it displays both the hint and the default text at once.

# Interact with Object

func _process(_delta):
	if not is_multiplayer_authority(): return
	var collider = raycastInteract.get_collider()

	if raycastInteract.is_colliding() and collider is Interactable:
		if currentCollider != collider:
			playingUI.setInteractableText(collider.get_script().getInteractableText())
			currentCollider = collider
			
		if Input.is_action_just_pressed("Interact"):
			destroyObject(collider)
			playingUI.setInteractableText(collider.get_script().getInteractableText())
	elif currentCollider:
		currentCollider = null
		playingUI.setInteractableText("")
	else:
		playingUI.setInteractableText("")

# Destroy Object
func destroyObject(object):
	object.queue_free()

# Display Text
func setInteractableText(text):
	if text == "":
		interactionLabel.set_text("")
		interactionLabel.set_visible(false)
	else:
		interactionLabel.set_text("Press E to %s" % text)
		interactionLabel.set_visible(true)

Hi @NCP_Bails, the interactable only gets destroyed for a single player because that’s only where you call the method. To let all the players know that the object should be destroyed, use an RPC.

1 Like

When i put @rpc above it, it didn’t change anything.
I couldn’t figure it out and I could only find examples of using rpc for player joining and such.

Yes because the @rpc annotation is only half of it :slight_smile: You need to call it as an RPC, not a regular function call.

Something like this:

func _process(_delta):
    # ...
    rpc("destroyObject", collider)

@rpc
func destroyObject(object):
	object.queue_free()

The issue with that IIRC is that node references don’t work as RPC parameters, but you should be able to use node paths. Also, you might want to configure the RPC so it’s reliable, can only be called by the player who owns the node, and is run locally too so the object disappears for the current player and everyone else too:

func _process(_delta):
	# ...
	rpc("destroyObject", collider.get_path())

@rpc("authority", "reliable", "call_local")
func destroyObject(node_path):
	var object = get_node(node_path)
	object.queue_free()

Basically, whenever you want a piece of code to be run for other players as well, you can use an RPC like above.

3 Likes

Perfect, works like a charm.
Thanks!

1 Like

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