远程操作

网络系统可以通过网络执行操作。这些类型的操作有时称为远程过程调用。在网络系统中有两种类型的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。它们不能是其他类型,不能通过网络序列化。

?