网络系统允许在网络上执行远程的动作。这类动作有时也叫做远程过程调用(RPC)。有两种类型的远程过程调用,命令(Commands) – 由客户端发起,运行在服务器上;和客户端远程过程调用(ClientRpc) - 服务器发起,运行在客户端上。
命令从客户端上的物体发给服务器上的物体。出于安全考虑,命令只能从玩家控制的物体上发出,因此玩家不能控制其他玩家的物体。要把一个函数变成命令,需要给这个函数添加[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);
}
}
}
注意如果每一帧都发送命令消息,会产生很多的网络流量。
默认情况下,命令是通过0号通道(默认的可靠传输通道)进行传输的。所以默认情况下,所有的命令都会被可靠地发送到服务器。可以使用命令的“Channel”参数修改这个配置。参数是一个整数,表示通道号。
1号通道是默认的不可靠传输通道,如果要用这个通道,把这个参数设置为1,示例如下:
[Command(channel=1)]
从Unity5.2开始,可以从拥有客户端授权的非玩家物体发出命令。这些物体必须是使用函数NetworkServer.SpawnWithClientAuthority()派生出来的,或者是使用NetworkIdentity.AssignClientAuthority()授权过的。从物体发送出来的命令会在服务器上运行,而不是在相关玩家物体所在的客户端上。
客户端远程过程调用从服务器的物体发送到客户端的物体上去。他们可以从任何带有NetworkIdentity并被派生出来的物体上发出。因为服务器拥有授权,所以这个过程不存在安全问题。要把一个函数变成客户端远程过程调用,需要给函数添加[ClientRpc]属性,并且为函数名添加“Rpc”前缀。这个函数将在服务端上被调用时,在客户端上执行。所有的参数都将自动传给客户端。
客户端远程调用必须带有“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);
}
}
当使用伺服器模式运行游戏的时候,客户端远程调用将在本地客户端执行 – 即使他其实和服务器运行在同一个进程。因此本地客户端和远程客户端对客户端远程过程调用的处理是一样的。
如果想将[ClientRpc]用在点击事件的同步操作上,不能直接绑定点击事件函数,而是应该起一个新的Rpc函数,点击事件去绑定这个Rpc函数,Rpc函数里才是对点击事件的操作: