Introductory question about RPC

Godot Version

4.4.1 .NET (.NET is needed only for compatibility with some external libraries. This question is all gdscript)

Question

I’m trying to do multiplayer in Godot for the first time. I’m a little confused about the rpc method tag. I have this function at a scene root that I run with 2 instances:

@rpc("any_peer", "call_remote")
func relay_make_choice_remote(data:Dictionary, actor):
	print("relaying choice from ", multiplayer.get_remote_sender_id(), " to ", multiplayer.get_unique_id())
	make_choice_remote.emit(data, actor)

It is called by a signal from lower in the scene.

In the same script, I have a very brief multiplayer setup (courtesy of this yt tutorial):

#Called when the "Host" button is pressed.
func _on_host_pressed() -> void:
	peer.create_server(port)
	multiplayer.multiplayer_peer = peer
	#pass the id of connecting players to a player constructor
	multiplayer.peer_connected.connect(_add_player)

	#create a player for the host to use
	var player = _add_player(1)
	
	print("created server on port ", port)

#The "player" is not relevant as of yet. Just the existence of the host and client.
func _add_player(id:int) -> Node:
	if !player_scene: return null
	
	var player = player_scene.instantiate()
	player.name = str(id)
	#add the player to the tree
	add_child.call_deferred(player)
	
	print("Created player ", player)
	return player

#Called when the "Join" button is pressed.
func _on_join_pressed() -> void:
	peer.create_client("localhost", port)
	multiplayer.multiplayer_peer = peer
	print("connected to server ", peer)

Since the default host id is “1”, I would expect the result when triggering the signal connected to relay_make_choice_remote to be something like “relaying choice from 1 to 2”, and the result of the same signal in the second instance “relaying choice from 2 to 1.” However, the results are “relaying choice from 0 to 1” (host instance) and “relaying choice from 0 to 745385639” (client instance). That’s not what I expected at all!

Next, I added a Label to my scene displaying the number of times the make_choice_remote signal had been received. I kind of expected this, but it’s still disappointing that each instance was basically sending the signal to themselves. This was the case whether or not I used “call_remote” or “call_local” in the @rpc tags.

My question is: What am I doing wrong? Is it possible to send a call between peers using a signal?

Context

I have a dialogue system that I’m trying to port to multiplayer. After looking at some tutorials, I feel I know the easiest way to approach this. I’m not sure how relevant the exact approach is to my problem. But, if you’re willing, brace yourself for a slightly abstract explanation:

All clients have a copy of the dialogue tree, which is loaded from a file. Each copy of the dialogue tree can tell who is trying to access it by a character name (actor in the code above), and is able to display available choices, and process incoming choices using that character as context. This part of the code is finished, and works quite well.

Then, the different clients can send choices to each other over the internet… Just the local network would be good for now. Then, each local copy of the dialogue processes the choices coming in over the network to allow for progress through the dialogue tree in all instances.

In theory, this is as simple to implement as completing that relay_make_choice_remote method above!

You have to call RPCs via the rpc method; e.g. relay_make_choice_remote.rpc(data, actor). Almost everything you need to know about RPCs can be found in the Callable and Node doc pages (object.method without parentheses creates a callable). Callable — Godot Engine (stable) documentation in English
Node — Godot Engine (stable) documentation in English

2 Likes

Got it! The only extra nuance is that I needed to make a write a wrapper function since signals don’t support rpc calling directly. I was just a little greedy with reading through the high level multiplayer docs, so I missed that detail in the very first sentence. I think I should take a break tomorrow, lol.

FYI, you only ever know that the host will be 1. The other IDs are randomly generated at runtime and differ every time. They are valid UIDs only for that session.

1 Like

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