请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
 

Remote Actions

 
 
The network system has ways to perform actions across the network. These type of actions are sometimes called Remote Procedure Calls. There are two types of RPCs in the network system, Commands - which are called from the client and run on the server; and ClientRpc calls - which are called on the server and run on clients. 网络系统有若干方法,通过网络去执行一些操作(perform actions)。这些操作有时候被称为远过程调用(Remote Procedure Calls,RPC)。在网络系统中,有两种远过程调用,一种被称为Commands:即是由客户端发起,在服务端中调用,另一称为ClientRpc calls。即在服务端发起调用,在客户端上执行。
 
The diagram below shows the directions that remote actions take: 下面的流程图展示了remote actions的执行方式:
 
 
Commands
 
Commands are sent from player objects on the client to player objects on the server. For security, Commands can only be sent from YOUR player object, so you cannot control the objects of other players. To make a function into a command, add the [Command] custom attribute to it, and add the “Cmd” prefix. This function will now be run on the server when it is called on the client. Any arguments will automatically be passed to the server with the command. Commands由在客户端的player object发送到服务端对应的那个player object。为了安全考虑。Commands只能由你自己的客户端的player object发送。所以你不能控制其他人的player object。要把一个函数设置为Commands的,需要在该函数签名前增加一个[Command]属性标签。并且该函数的签名必须以“Cmd”为前缀。只要这样做,这个函数便能在客户端发起,在服务端中调用。所有的传递给该函数的参数,将会自动地发送到服务端
 
Commands functions must have the prefix “Cmd”. This is a hint when reading code that calls the command - this function is special and is not invoked locally like a normal function. Commands函数必须有“Cmd”的函数名前缀。这是一个标识提示,这将告诉大家,这个函数是特殊的,不能像一般函数那样子,仅在本地调用执行。如下代码:
 

class Player : NetworkBehaviour
{
    public GameObject bulletPrefab;

    [Command]
    void CmdDoFire(float lifeTime)
    {
        GameObject bullet = (GameObject)Instantiate(
            bulletPrefab, 
            transform.position + transform.right,
            Quaternion.identity);
            
        var bullet2D = bullet.GetComponent<Rigidbody2D>();
        bullet2D.velocity = transform.right * bulletSpeed;
        Destroy(bullet, lifeTime);

        NetworkServer.Spawn(bullet);
    }

    void Update()
    {
        if (!isLocalPlayer)
            return;

        if (Input.GetKeyDown(KeyCode.Space))
        {
            CmdDoFire(3.0f);
        }
    }
}

 
Be careful of sending commands from the client every frame! This can cause a lot of network traffic. 要很注意要避免在客户端的每一帧中调用这些Commands函数,这将会引起很严重的网络堵塞。
 
By default, Commands are sent on channel zero - the default reliable channel. So by default all commands are reliably sent to the server. This can be customized with the “Channel” parameter of the [Command] custom attribute. This parameter should be an integer, representing the channel number. 默认地,Commands将在零号通道(channel zero),即默认的可靠通道中发送。所以默认地所有Commands都将可靠地发送给服务端。当然可以把指定的使用哪个通道的参数值“Channel”传递给Commands函数。这个参数必须是一个整数。对应一个通道编号。
 
Channel 1 is also set up by default to be an unreliable channel, so to use this, use the value 1 for the parameter in the Command attribute, like this: 1号通道被默认地设置为一个不可靠的(unreliable)通道。所以要使用1号通道的话,需要在Command属性标签中指定该参数值,如下代码所示:
 
[Command(channel=1)]
 
Starting with Unity release 5.2 it is possible to send commands from non-player objects that have client authority. These objects must have been spawned with NetworkServer.SpawnWithClientAuthority or have authority set with NetworkIdentity.AssignClientAuthority. Commands sent from these object are run on the server instance of the object, not on the associated player object for the client. 从Unity5.2开始。可以从一个non-player object处发送Commands。要求是该object必须有客户端授权(client authority)。并且,这些object需要通过调用NetworkServer.SpawnWithClientAuthority方法生成,或者通过NetworkIdentity.AssignClientAuthority方法设置得到客户端授权。由这些object发送的Commands,将由服务端中对应的object去执行,而不是对应的客户端object执行。
 
ClientRpc Calls
 
ClientRpc calls are sent from objects on the server to objects on clients. They can be sent from any server object with a NetworkIdentity that has been spawned. Since the server has authority, then there no security issues with server objects being able to send these calls. To make a function into a ClientRpc call, add the [ClientRpc] custom attribute to it, and add the “Rpc” prefix. This function will now be run on clients when it is called on the server. Any arguments will automatically be passed to the clients with the ClientRpc call.. ClientRpc calls则是由在服务端中的object发送到客户端。所有的带有NetworkIdentity组件的,由服务端生成的object都能发送ClientRpc call。因为服务端已经对之授权(has authority),所以发送ClientRpc call是没有安全问题的。要把一个函数声明为ClientRpc call。需要在函数签名前加上[ClientRpc]属性标签。并且在函数签名加上Rpc前缀。这些函数便可以由服务端发起,由各个客户端执行。所有传递给这些函数的参数,将会自动地由服务端发送到客户端。
 
ClientRpc functions must have the prefix “Rpc”. This is a hint when reading code that calls the method - this function is special and is not invoked locally like a normal function. ClientRpc函数必须以Rpc前缀命名。这是一个标识提示,这将告诉大家,这个函数是特殊的,不能像一般函数那样子,仅在本地调用执行。如下代码:
 

class Player : NetworkBehaviour
{
    [SyncVar]
    int health;

    [ClientRpc]
    void RpcDamage(int amount)
    {
        Debug.Log("Took damage:" + amount);
    }

    public void TakeDamage(int amount)
    {
        if (!isServer)
            return;

        health -= amount;
        RpcDamage(amount);
    }
}

 
When running a game as a host with a LocalClient, ClientRpc calls will be invoked on the LocalClient - even though it is in the same process as the server. So the behaviour of LocalClients and RemoteClients is the same for ClientRpc calls. 当在一个host上运行游戏的时候,ClientRpc call将会在本地客户端上执行——尽管这个本地客户端和服务端是在同一个进程。所以,对于本地客户端和远程客户端而言,进行ClientRpc调用的代码都是一样的。
 
Arguments to Remote Actions
 
The arguments passed to commands and ClientRpc calls are serialized and sent over the network. These arguments can be: 传递给Commands和ClientRpc call的函数的参数,将会被序列化和通过网络发送,这些参数可以是:
 
basic types (byte, int, float, string, UInt64, etc)
arrays of basic types
structs containing allowable types
built-in unity math types (Vector3, Quaternion, etc)
NetworkIdentity
NetworkInstanceId
NetworkHash128
GameObject with a NetworkIdentity component attached
基本内置类型(byte, int, float, string, UInt64, etc)
基本内置类型的数组
包含所允许的数据类型的结构体
Unity3D引擎内建的数学类型,如Vector3,Quaternion等等
NetworkIdentity
NetworkInstanceId
NetworkHash128
挂接了NetworkIdentity组件的game object
 
Arguments to remote actions cannot be subcomponents of GameObjects, such as script instances or Transforms. They cannot be other types that cannot be serialized across the network. 传递给作为remote actions的函数的参数,不能是GameObjects的子类型,比如Transforms类,这些不能被序列化后通过网络传递发送。