携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情
ClientRpc
ClientRpc即服务器发起的,调用客户端上的方法的远程命令。服务器上的任意具有Network Identity组件的对象都可以发起ClientRpc。
- 将一个函数设置为ClientRpc需要给他加上一个自定义属性
[ClientRpc]。 - ClientRpc函数按照惯例添加前缀"Rpc"
- ClientRpc函数的参数类型必须是Mirror支持的类型。
- ClientRpc函数不能有返回值
- ClientRpc函数是由客户端的网络对象执行的,因此需要存在于继承自NetworkBehaviour的脚本中。
一个例子:
public class Player : NetworkBehaviour
{
int hp;
[ServerCallback]
public void TakeDamage(int damage)
{
hp -= damage;
RpcDamage(damage);
}
[ClientRpc]
public void RpcDamage(int damage)
{
PlayAttackEffect(damage);
}
}
在这个例子中,TakeDamage是一个在服务器上被执行的方法,注意他被标记了属性[ServerCallback],如果客户端执行这个方法会忽略掉。当然也可以在这个方法内部判断isServer。该服务器方法内部会调用RpcDamage方法,这是一个ClinetRpc方法,会被发送给客户端上相应的Player对象脚本去执行。在ClientRpc方法内部一般会进行一些只需要在客户端进行的操作,比如播放特效。
排除对象拥有者
ClientRpc消息会被发送给该对象的所有观察者,而Player对象也是他们自己的观察者。在某些情况下,你可能不需要对象调用针对自己的ClientRpc。这可以通过给[ClientRpc]增加一个参数:
[ClientRpc(includeOwner = false]
TargetRpc
ClientRpc是从服务器给所有客户端群发消息,如果想向特定的客户端单独发送消息,就要使用TargetRpc。
- 将一个函数设定为TargetRpc需要给它添加自定义属性
[TargetRpc] TargetRpc函数按照惯例使用前缀Target- 如果TargetRpc函数的第一个参数的类型为
NetworkConnection,那么该Rpc调用则由这个Connection对应的对象接收。 - 如果TargetRpc函数的第一个参数是其他类型,那么包含该TargetRpc函数的脚本的拥有者在客户端上的对象作为Rpc调用的接收者。
一个例子:
public class Player : NetworkBehaviour
{
int hp;
[Command]
public void CmdMagic(GameObject target, int damage)
{
target.GetComponent<Player>().hp -= damage;
NetworkIdentity targetIdentity = target.GetComponent<NetworkIdentity>();
TargetDoMagic(targetIdentity.connectionToClient, damage);
}
[TargetRpc]
public void TargetDoMagic(NetworkConnection target, int damage)
{
//攻击目标的客户端会执行该方法
PlayerMagicEffectOnMe();
}
[Command]
public void CmdHealSelf()
{
hp += 10;
TargetHealed(10);
}
[TargetRpc]
publc void TargetHealed(int amount)
{
//没有NetworkConnection参数,因此该脚本的拥有者对象执行该方法
PlayerHealEffectOnMe();
}
}
这个例子中展示了[Command]和Rpc方法的通常用法。使用Mirror写网络游戏时,一定要区分哪些操作是在服务器执行,哪些是在客户端执行。在这儿,CmdMagic和CmdHealSelf都是在服务器上执行的Command方法,在其内部会进行Player的hp值的操作,然后在Command内部调用Rpc方法,让客户端去执行其他需要在客户端上进行的操作,比如更新UI或者播放特效等等。这个例子展示了两类TargetRpc,其中TargetDoMagic是在指定的客户端进行操作,而TargetHealed是对拥有者操作。