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

Posted

技术标签:

【中文标题】统一3D。试图在没有权限的情况下为对象发送命令【英文标题】:Unity3D. Trying to send command for object without authority 【发布时间】:2016-07-06 14:14:28 【问题描述】:

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

这是我的做法: 游戏管理器对象是 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,字符串)

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

【问题讨论】:

【参考方案1】:

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

试图为未经授权的对象发送命令

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

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

但是

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

那么解决办法是什么: 在发送 Command(或执行 command 函数)之前,将该对象的权限分配给您的播放器。像这样的

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

"this" 将代表您的 Player 对象。 Command 调用后,您可以使用此代码 sn-p 删除权限。

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

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

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

【讨论】:

【参考方案2】:

你不能在没有本地权限的情况下发送命令。

if (!isLocalPlayer) return;

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

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

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

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

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

【讨论】:

我遇到了类似的问题,但是我的命令在 OnStartLocalClient 函数中,所以这不应该工作吗? 我认为您使用了错误的方法名称,请尝试 OnStartLocalPlayer docs.unity3d.com/ScriptReference/…【参考方案3】:

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

[Command(requiresAuthority = false)]
public void Something ()
   

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于统一3D。试图在没有权限的情况下为对象发送命令的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在没有 root 权限的情况下为 SQL 服务器安装 unixODBC 驱动程序

在没有服务器的情况下为对等通信更改 2 个客户端套接字?

matplotlib (python) - 在没有 pyplot 的情况下为多个绘图创建单个自定义图例

在没有v-model且没有数据绑定的情况下为输入赋值

我试图统一创建一个 3d 指南针,但针无法与指南针的主体一起旋转

如何在不放弃主线程的情况下为 Python 使用 CoreBluetooth