远程操作

网络系统可以通过网络执行操作。这些类型的操作有时称为远程过程调用。在网络系统中有两种类型的RPC,Command - 从客户端调用并在服务器上运行; 和ClientRpc调用 - 在服务器上调用并在客户端上运行。

下图显示了远程操作的方向:

Command

Command从客户端上的玩家对象发送到服务器上的玩家对象。为了安全起见,Command只能从您的玩家对象发送,因此您无法控制其他玩家的对象。要将一个函数变成一个命令,添加[Command]自定义属性,并添加“Cmd”前缀。当在客户端上调用该函数时,该函数现在将在服务器上运行。任何参数将自动通过该命令传递给服务器。

命令函数必须具有前缀“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);
            }

        }
    }

小心每帧发送来自客户端的命令!这可能会导致大量网络流量。

默认情况下,命令在零通道 - 默认可靠通道上发送。所以默认情况下,所有命令都可靠地发送到服务器。可以使用[Command]自定义属性的“Channel”参数进​​行自定义。该参数应该是一个整数,代表通道号。

通道1也默认设置为不可靠通道,因此要使用此参数,请在Command属性中将参数值设为1,如下所示:

    [Command(channel=1)]

从Unity 5.2版开始,可以从具有客户端权限的非玩家对象发送命令。这些对象必须由NetworkServer.SpawnWithClientAuthority产生,或通过NetworkIdentity.AssignClientAuthority设置权限。从这些对象发送的命令在对象的服务器实例上运行,而不是在客户端的关联玩家对象上运行。

ClientRpc呼叫

ClientRpc调用从服务器上的对象发送到客户端上的对象。它们可以从任何带有已生成的NetworkIdentity的服务器对象发送。由于服务器具有权限,因此服务器对象无法发送这些调用的安全问题。为了使函数进入ClientRpc调用,添加[ClientRpc]自定义属性,并添加“Rpc”前缀。当在服务器上调用该函数时,该函数现在将在客户端上运行。任何参数将自动通过ClientRpc调用传递给客户端。

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);
        }
    }

当使用LocalClient作为主机运行游戏时,ClientRpc调用将在LocalClient上调用 - 即使它与服务器在同一进程中。因此,LocalClientsRemoteClients的行为对于ClientRpc调用而言是相同的。

对远程操作的参数

传递给命令和ClientRpc调用的参数被序列化并通过网络发送。这些数据可以是:

    • 基本类型(byte,int,float,string,UInt64等)
    • 基本类型的数组
    • 包含允许类型的结构
    • 内置的Unity数学类型(Vector3,Quaternion等)
    • NetworkIdentity
    • NetworkInstanceId
    • NetworkHash128
    • 带有NetworkIdentity组件的GameObject

对远程操作的参数不能是GameObjects的子组件,例如脚本实例或Transform。它们不能是其他类型,不能通过网络序列化。

🔚