This site is currently in read-only mode during migration to a new platform.
You cannot post questions, answers or comments, as they would be lost during the migration otherwise.
+1 vote

Naturally these are new to 2.2 and thus no documentation has been made yet so hopefully I am asking this question fresh enough that the implementors of the networking in 2.2 still know the code they recently wrote:

I am trying to understand the behavior of the new Node.rpc() call and friends...

SomeNode.rpc("foo") is a broadcasted message?
From what has been responded on FB this should broadcast a method call to every connected peer's /root/nodepath/to/ (assuming declares foo with remote keyword)?

Similar to above but only generates a call to peer 1000's /root/nodepath/to/

Finally, no return values? So two-way methods require providing the caller id's as arguments in eg: SomeNode.rpc_id(1,"foo",1000,arg1,arg2,...,argN) {assume peer 1000 is asking server (1) a foo related question here} and "return" a value with self.rpc_id(1000,"foo_response",1,retval)?

My worry here is the call/return is completely non-atomic and something affecting foo's computation could happen between foo() call on server and peer 1000 receiving foo_response().

in Engine by (45 points)

1 Answer

–1 vote
Best answer

That's right, NodePath determines which nodes get called. rpc() is a broadcast message, the function to call on each peer is determined by remote/sync/master/slave. rpc_id() also correct, it's a direct rpc call on a peer.

Computing via a network is an example of something called distributed computing, where instances work in parallel and communicate through asynchronous channels. If you really need to you can lock an objects state after an rpc() with a simple flag value (something like a mutex?), but this should not be required if the object is completely in slave or master mode.
Physics synchronisation is another subject. Usually if you rpc() position and velocity it should be enough. Sometimes you might want to disable collisions on slaves and additionaly receive collision events (simulate "bumping" locally). It really depends on your own project.

As for return values, your approach is the one to use. You can do some tricks here and even use a yield keyword to stop your method execution state.

var response_data
signal reponse_received

remote func foo_response(data):
  response_data = data

func foo():
  yield(self, "response_received")
  print("Received "+str(response_data))    
  • I'm not sure if yield returns signal's data with it so an additional variable is needed.
by (42 points)
selected by

Do the nodetypes matter or just the name of the node for .rpc() and friends? So on the calling end maybe it's just a proxy Node at the calling end to refer to a real node (actual render object, such as a Spatial) at the peer?

A: As far as I can see the object may be any type of Node. It's not restricted to the same object type as other peers, only that the NodePath matches up.

Great, thanks for the tip.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.