Unet 的[Command]和[ClientRpc]简单理解就是;
[Command]是指客户端向服务器发送指令,方法体结果在服务器里面执行,方法在客户端调用
[ClientRpc]是指服务器向所有连接的客户端发送指令,方法体结果在客户端里面执行,方法在服务器调用
这几句解释很笼统不好理解,下面我们一点一点来用实验解析:
首先在Unity里制作一个工程,制作了一个玩家的预制:
具体添加什么组件前面的文章已经详细说过就不在说明了,这个的作用就是鼠标左键点击增加数字然后显示在UI上。
添加如上图的脚本,首先编写如下代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Rpc_Cmd_Test : NetworkBehaviour
{
public Text text;
private int _number;
private void Update()
{
if (!isLocalPlayer) return;
if (Input.GetMouseButtonDown(0))
{
NumberChange();
ShowNumber();
}
}
public void NumberChange()
{
_number++;
}
public void ShowNumber()
{
text.text = _number.ToString();
}
}
很简单,就不作注释了,记得给text赋值,我们来看下效果:
服务器:
客户端:
可以发现,服务器和客户端各自做着各自的事情互bu干扰,因为方法只在各自本地执行
我们下面我们为NumberChanger方法添加[Command]指令
再次运行:
服务器效果
客户端效果:
当我在服务器点击鼠标左键的时候服务器运行没有问题,但是客户端点击鼠标左键数字没有任何变化,由此我们可以看出。
当给一个方法添加[Command]特性以后,该方法在客户端被调用,由客户端发送指令给服务器让服务器执行方法里面的代码。
由于代码在服务器执行,又没有广播给客户端,所以客户端是不会作出响应的。
那我们如何让客户端也能作出反应呢?下面我们看看[ClientRpc],在代码里添加一个方法:
修改Update里面调用的方法:
我们看看效果:
服务器:
客户端:
这次我把Unity这边当做的客户端,可以看到服务器没有问题,但是客户端数值没有变化并且报错:
大意就是RpcNumberChange方法在客户端调用,说明了带有[ClientRpc]的方法不能直接在客户端调用,那么应该怎么调用呢?
我把代码做了如下修改:
在CmdNumberChangge里面调用RpcNumberChange方法,然后在Update调用CmdChangeNumber方法,我们来看效果:
服务器:
客户端:
可以看到服务器和客户端都对鼠标点击左键有了响应,为什么呢?原因就在与[ClientRpc]指定的方法是由服务器远程控制所有连接服务器的客户端执行方法里面的代码,方法是在服务器调用,方法里面的代码在客户端执行,上面的代码把Rpc方法放在了Cmd方法里面,那么由于Cmd方法里面的代码会在服务器执行,那么Rpc方法也会在服务器里面调用,那么客户端得到的结果其实是由于执行了方法里面的代码而得到的结果。
上面的话很绕,简单理解就是Rpc方法放在Cmd方法里面调用,那么客户端执行完Rpc里面的代码后由服务器调用就可以得到Rpc代码执行的结果
下面让两边的显示同步:
只需要把ShowNumber方法放到Rpc方法里面。
我们看效果:
完美,那么[SyncVar]干嘛用的呢?其实就是把指定的变量变成服务器变量,看代码:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
public class Rpc_Cmd_Test : NetworkBehaviour
{
public Text text;
[SyncVar(hook ="ShowNumber")]
private int _number;
private void Update()
{
if (!isLocalPlayer) return;
if (Input.GetMouseButtonDown(0))
{
CmdNumberChange();
// ShowNumber();
}
}
[Command]
public void CmdNumberChange()
{
RpcNumberChnage();
}
// [ClientRpc]
public void RpcNumberChnage()
{
_number++;
//ShowNumber();
}
public void ShowNumber(int number)
{
if (isClient)
{
text.text ="Client : "+ number.ToString();
}
if (isServer)
{
text.text = "Server : " + number.ToString();
}
}
}
我为[SyncVar]添加了一个方法,该方法必须带有参数。参数代表的就是[SyncVar]指定的变量(_number)当_number发生变化时,就会在服务器调用添加的方法,由于_humber是在服务器进行的操作然后传递给客户端,所以我们就不需要Rpc方法来得到
结果。欢迎加群:4364930讨论。