Making “direct” RPC style calls in new Unity netwo

2019-02-18 03:17发布

Say you have

enter image description here

Using "new" Unity networking, you must have (as far as I know) a NetworkManager somewhere. It will spawn the ridiculous "player" object.

The ridiculous "player" object must have a class which inherits from NetworkBehaviour.

Most teams call that class something like "Comms" or "AbstractPlayer" or "Junction".

public class Comms : NetworkBehaviour { }

So, every command (like "Jump") has to be mediated by that "Comms" class.

For each command (like "Jump") you need a pair of functions in the Comms class:

public class Comms : NetworkBehaviour {

    // for every command (say, "Jump") you need THIS PAIR of functions:

    public void CommandJump() {
        Debug.Log("this is comms - client, do a Jump");
        CmdJump();
    }

    [Command]
    void CmdJump() {
        Debug.Log("this is comms - server. a Jump arrived");
        // simply pass on that command to the correct script on a server...
        s = Object.FindObjectOfType<Some Class On The Server>();
        s.ClientJumped();
    }
}

So!

With new Unity networking, in the client side, every time you want to

send to server Jump()

you in fact have to send it VIA the "comms" class on the abstract player.

public class Jumping: MonoBehavior...

    // here in the client side ... we want to send "Jump"
    Comms comms = Object.FindObjectOfType<Comms>();
    comms.CommandClick1();

(Note - obviously, you would cache the "comms" there. It's just an example.)

Aside: extremely important: that is just a outline example.

In practice you must do this:

https://stackoverflow.com/a/51759299/294884

So!

the thing is this:

in "old" Unity networking, any old client script could just directly make a network call ("CmdJump" in the example). All you needed was a link to a NetworkView.

Now you have to have this new "in-between" class, "Comms" in the example.

I am trying to understand,

is there a way for a normal script on the client side (like Jumping - a MonoBehavior) to directly call a Command?

As far as I know, only NetworkBehaviour derived classes can do that. In the old networking, any class could make such a call.

In "new" Unity networking, as far as I know you must you pass every call through a NetworkBehaviour derived class, as in my example here.

As you can see, if I am "missing something," and the classes such as Jumping can just do it directly, then my code is heinous :)

Can you call Commands directly from in a MonoBehavior?

Am I in fact completely wrong that you have to have the ridiculous auto-spawned "player" objects, and so on? Maybe there's an entirely other way to call Commands.

1条回答
啃猪蹄的小仙女
2楼-- · 2019-02-18 03:58

The short answer to your question is No. Simply because using the [Command] keyword in a MonoBehavior will immediately result in an error in your editor, since the code can't be compiled.

UNetWeaver error: Script XXXXXX uses [Command] YYYYY but is not a NetworkBehaviour.

However there are other possibilities that get very close to what you want to achieve.

  • As discussed in the comments, you could use Events and Delegates to subscribe your [Command] function to another function from a class that inherits from MonoBehavior.
  • Another very clever possibility that I have just attempted and had success with is using Interfaces.

I have just made a simple interface that does not implement any other interfaces, it just declares a command. It looks like this:

public interface ICustomCommands
{
    [Command]
    void CmdCustomSpawn(GameObject toSpawn);
}

Then I made a simple class that will implement this interface (the one method) without using the [Command] keyword. My custom class inherits from MonoBehavior and looks like this:

public class CustomCommands : MonoBehaviour, ICustomCommands
{
    public void CmdCustomSpawn(GameObject toSpawn)
    {
        NetworkServer.Spawn(toSpawn);
    }
}

I was then successfully able to call my CmdCustomSpawn function and spawn a player on the server.

查看更多
登录 后发表回答