Unity3D。试图在没有权限的情况下发送对象命令

时间:2016-03-19 22:14:46

标签: c# networking unity3d unity3d-unet

我有一个多人回合制战略游戏,需要一个游戏经理,控制当前的游戏状态(轮到谁了)。这个管理器应该对每个客户端都是通用的,它的状态应该在服务器上同步。

以下是我这样做的方式: 游戏管理器对象是NetworkBehaviour,它具有NetworkIdentity,它不是本地播放器权限,也不是服务器权限。我已经制作了一个自定义的NetworkManager,它在客户端连接上生成游戏管理器,还测试它是否是服务器。这是一个代码:

public override void OnClientConnect(NetworkConnection conn)
    {
        ClientScene.Ready(conn);
        if (NetworkServer.active)
        {
            var manager = Instantiate(MultiplayerManagerPrefab, Vector3.zero, Quaternion.identity) as GameObject;
            var tacticsManager = manager.GetComponent<MultiplayerManagerModel>();
            NetworkServer.RegisterHandler(MsgType.AddPlayer, tacticsManager.CreatePlayerOnServer);
            NetworkServer.Spawn(manager);
        }
        ClientScene.AddPlayer(0);
    }

当我在服务器上运行它时工作正常,它在客户端上创建一个实例并同步从服务器到客户端的变量。但是当我尝试从客户端运行命令时,它会忽略它们,抛出这个警告:

  

尝试在没有权限的情况下发送对象命令。   UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter,   Int32,String)

请注意,此游戏管理器是在任何玩家之前生成的,因为它必须负责产生玩家。我做错了什么?

2 个答案:

答案 0 :(得分:11)

在您的代码片段旁边,警告

  

尝试在没有权限的情况下为对象发送命令

表示:您从权限,您的(玩家)没有的对象发送命令

Unity文档声明的内容: 命令从客户端上的播放器对象发送到服务器上的播放器对象。为安全起见,命令只能从您的玩家对象发送,因此您无法控制其他玩家的对象。

<强> BUT

  

从Unity版本5.2 开始,可以从中发送命令   具有客户端权限的非玩家对象。这些对象必须具有   已经使用NetworkServer.SpawnWithClientAuthority生成或拥有   使用NetworkIdentity.AssignClientAuthority设置的权限。命令   从这些对象发送的是在对象的服务器实例上运行的,   不在客户端的关联播放器对象上(more)。

那么解决方案是什么: 在发送 命令 (或执行命令功能)之前,将该对象的权限分配给您的播放器。像这样的东西

Cloning into '***'...
remote: Counting objects: 13197, done.
fatal: early EOFs:   1% (135/13197), 116.01 KiB | 6.00 KiB/s
fatal: The remote end hung up unexpectedly
fatal: index-pack failed
error: RPC failed; curl 56 SSL read: error:00000000:lib(0):func(0):reason(0), errno 10054

”将代表您的Player对象。进行 Command 调用后,您可以使用此代码段删除权限。

assignAuthorityObj.GetComponent<NetworkIdentity>().AssignClientAuthority(this.GetComponent<NetworkIdentity>().connectionToClient);

同样,“”将代表您的玩家对象。

重要提示 :我通常使用 OnTriggerEnter 指定对象的权限(如果我想使用它)并删除权限在 OnTriggerExit 。它取决于您希望获取或删除对象权限的特定情况。

答案 1 :(得分:5)

您无法在没有当地授权的情况下发送命令。

if (!isLocalPlayer) return;

但是,您使用此命令发送了哪种数据? 总的来说,正如你所说:

&#34;它的状态应该在服务器&#34;

上同步

所以,恕我直言,你没有理由从你的播放器发送Command。 命令应该是播放器输入。 这些输入将触发游戏中的操作。 您的经理将使用ClientRpc

从这些操作中获取信息(分数更新,游戏结束......)并在客户端上发送数据和/或触发操作

这是服务器权限模型。如果您让本地对象发送命令,黑客可以很容易地进入并告诉您的经理

&#34;嘿,轮到我了。嘿,轮到我了。嘿,我的分数是9999999,我在1秒内赢了比赛。&#34;。