• 远程操作
    • Command
    • ClientRpc呼叫
    • 对远程操作的参数

    远程操作

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

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

     6.27 远程操作  - 图1

    Command

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

    命令函数必须具有前缀“Cmd”。这是读取调用该命令的代码时的一个提示 - 该函数是特殊的,并不像普通函数那样在本地调用。

    1. class Player : NetworkBehaviour
    2. {
    3. public GameObject bulletPrefab;
    4. [Command]
    5. void CmdDoFire(float lifeTime)
    6. {
    7. GameObject bullet = (GameObject)Instantiate(
    8. bulletPrefab,
    9. transform.position + transform.right,
    10. Quaternion.identity);
    11. var bullet2D = bullet.GetComponent<Rigidbody2D>();
    12. bullet2D.velocity = transform.right * bulletSpeed;
    13. Destroy(bullet, lifeTime);
    14. NetworkServer.Spawn(bullet);
    15. }
    16. void Update()
    17. {
    18. if (!isLocalPlayer)
    19. return;
    20. if (Input.GetKeyDown(KeyCode.Space))
    21. {
    22. CmdDoFire(3.0f);
    23. }
    24. }
    25. }

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

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

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

    1. [Command(channel=1)]

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

    ClientRpc呼叫

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

    ClientRpc函数必须具有前缀“Rpc”。当读取调用方法的代码时这是一个提示 - 这个函数是特殊的,并不像普通函数那样在本地调用。

    1. class Player : NetworkBehaviour
    2. {
    3. [SyncVar]
    4. int health;
    5. [ClientRpc]
    6. void RpcDamage(int amount)
    7. {
    8. Debug.Log("Took damage:" + amount);
    9. }
    10. public void TakeDamage(int amount)
    11. {
    12. if (!isServer)
    13. return;
    14. health -= amount;
    15. RpcDamage(amount);
    16. }
    17. }

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

    对远程操作的参数

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

    1. 基本类型(byteintfloatstringUInt64等)
    2. 基本类型的数组
    3. 包含允许类型的结构
    4. 内置的Unity数学类型(Vector3Quaternion等)
    5. NetworkIdentity
    6. NetworkInstanceId
    7. NetworkHash128
    8. 带有NetworkIdentity组件的GameObject

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

    ?