godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.17k stars 21.19k forks source link

Networking: RPC Signals #37454

Closed maringuu closed 3 years ago

maringuu commented 4 years ago

I wonder if there is a way to send a signal over a Network. In my situation I want to send a "client ready" message to the server when the client has loaded the world and is ready to have the other players spawned.

With RPC this is not doable because the function does have to exist locally but the onClientReady method should only be implemented on the server.

My suggestion is that there should be some other kind of networked method call to call a method on a remote.

Am I missing anything? Would there be a correct way to implement this?

git2013vb commented 4 years ago

Like instead using: EmitSignal("mysignal", obj_where_method_is, "_on_my_method");

something like this?:

RpcEmitSignal("mysignal", obj_where_method_is, "_on_my_method");
RpcIDEmitSignal(1,"mysignal", obj_where_method_is, "_on_my_method");

But , the connection, how can be done? Which side will be in charge?

edit: Or maybe in this way:

EmitSignal("mysignal", remote_obj_where_method_is, "_on_my_method");
EmitSignal("mysignal", remote_obj_where_method_is[ID], "_on_my_method")

If is like this we will need something like this?:

[Puppet]
[Signal]
delegate void mysignal(int id);

So the remote object have to be shared/checked across network.. How will be the network performances?

maringuu commented 4 years ago

I think you confused EmitSignal with Connect. I think a combination of your two ideas looks good. Lets assume that for the Server and Client we have two seperate projects. In the client project Client.cs is a autoloaded singleton on /root/Network. In the server project Server.cs is a also autoloaded singleton on /root/Network

Client.cs

[Signal]
[Remote]
delegate void mysignal();

RpcEmitSignal("mysignal", obj_where_method_is);
// in our setup obj_where_method_is == this
Server.cs

obj_where_signal_is.RpcConnectSignal("mysignal", this , "on_my_signal");
// in our setup obj_where_signal_is == this

private void on_my_signal() {
    //...
}

But , the connection, how can be done? Which side will be in charge?

That is a good question. I think the party which receives the signal (the one on which actual code will be executed) should be in charge for connecting.

If is like this we will need something like this?

I think so too.

So the remote object have to be shared/checked across network.. How will be the network performances?

See above for a proposed sharing mechanism. I think this way the performance will just be as it is with current rpc.

maringuu commented 4 years ago

I got an idea. This would not really be signals but could be used like they were.

In the current networking code a rpc processed like this: https://github.com/godotengine/godot/blob/ea48b403a9e7b8ddb2b814c6ea413bb9f5ed0518/core/io/multiplayer_api.cpp#L1012-L1078 In short:

  1. Get rpc mode of locally existent function
  2. Execute locally when Sync
  3. Send over the network to remote peer id

When we would change the order to be:

  1. Execute locally when sync
  2. Send over the network to remote peer id
  3. Get rpc mode of locally existent function

It would allow to call a function that does not exist locally but on the remote. Then Node.ConnectRpc("method", object, "handler_method") could just set the [Remote] attribute on the Node object. Still somehow the emitter of the signal has to know which function to call on the remote... Maybe we could add some internal method that does this.

git2013vb commented 4 years ago

@maringuu I din't investigate in the code yet, but I have some reserve about all this: Nowadays network games are setup with authoritative server for several reasons - security in first place. I'm not sure how this impact the whole structure and how people are supposed to manage lag and other issues. While currently we sent our date by methods/properties and it is "easy" to check manage them if something like that will be implemented how we able to manage them? I'm not sure if we really we need at this point. Another side is IF the engine will be in charge of this problems but I doubt :)

edit: While to me make sense to have signals in "local" context I don't see the advantage to add such complexity to add remote signals when there is no chance that they will be done in "real-time". You know remote are working in the past.. :)

jonbonazza commented 4 years ago

This is probably a better fit for the proposals repo. Can you edit this post to follow tgat repo's issue template? Then @Calinou can move it

Calinou commented 3 years ago

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!