14

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

我是这样做的:游戏管理器对象是 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)

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

4

3 回答 3

15

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

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

意味着:您正在从您的(玩家)没有权限的对象发送命令。

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

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

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

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

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

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

同样,“ this ”将代表您的 Player 对象。

重要说明:我通常使用OnTriggerEnter分配对象的权限(如果我想使用它)并删除OnTriggerExit上的权限。这取决于特定场景,您希望在什么情况下获取或删除对象权限。

于 2017-03-09T07:51:14.323 回答
4

没有本地权限,您无法发送命令。

if (!isLocalPlayer) return;

但是,你用这个命令发送什么样的数据?一般来说,正如你所说:

“它的状态应该在服务器上同步”

所以,恕我直言,你没有理由Command从你的播放器发送一个。命令应该用于玩家输入。这些输入将触发您游戏中的操作。您的经理将从这些操作(得分更新、游戏结束...)中获取信息,并使用客户端发送数据和/或触发操作ClientRpc

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

“嘿嘿,轮到我了,嘿嘿,又轮到我了,嘿嘿,我的分数是9999999,1秒就赢了。”

于 2016-04-02T10:15:02.273 回答
0

如果您使用的是镜像,则使用绕过权限,花了一整天的时间来尝试实施上述不起作用的解决方案。这里应该怎么做:https ://mirror-networking.gitbook.io/docs/guides/communications/remote-actions

[Command(requiresAuthority = false)]
public void Something (){
   
}
于 2021-11-28T14:49:45.933 回答