简体   繁体   English

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

[英]Unity3D. Trying to send command for object without authority

I have a multiplayer turn-based strategy game that needs a game manager, controlling current game state (who's turn it is etc.).我有一个多人回合制策略游戏,它需要一个游戏管理器来控制当前的游戏状态(轮到谁等)。 This manager should be common for every client, it's state should be synchronized on server.这个管理器应该对每个客户端都是通用的,它的状态应该在服务器上同步。

Here's how I'm doing this: The game manager object is NetworkBehaviour and it has NetworkIdentity which is not local player authority nor server authority.我是这样做的:游戏管理器对象是 NetworkBehaviour,它具有 NetworkIdentity,它既不是本地玩家权限,也不是服务器权限。 I've made a custom NetworkManager and it spawns the Game Manager on client connect, also testing if it is a server.我制作了一个自定义 NetworkManager,它在客户端连接上生成游戏管理器,还测试它是否是服务器。 Here's a code:这是一个代码:

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);
    }

When I run it on a server it works fine, it creates an instance on a client and synchronizes variables from server to client.当我在服务器上运行它时它工作正常,它在客户端上创建一个实例并将变量从服务器同步到客户端。 But when I try to run commands from client it ignores them, throwing this warning:但是当我尝试从客户端运行命令时,它会忽略它们,并抛出此警告:

Trying to send command for object without authority.试图在没有权限的情况下向对象发送命令。 UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter, Int32, String) UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter, Int32, String)

Note that this Game Manager is spawned before any player is because it must be responsible for spawning players.请注意,此游戏管理器在任何玩家之前生成,因为它必须负责生成玩家。 What am I doing wrong?我究竟做错了什么?

Beside your code fragment, the warning 在您的代码片段旁边,警告

Trying to send command for object without authority. 试图在没有权限的情况下发送对象的命令

Means that: you are sending command from an object whose authority , your (player) don't have. 意味着:您从一个权限 ,您的(玩家)没有的对象发送命令

What Unity docs states: Commands are sent from player objects on the client to player objects on the server. Unity文档声明: 命令从客户端上的播放器对象发送到服务器上的播放器对象。 For security, Commands can only be sent from YOUR player object , so you cannot control the objects of other players. 为了安全起见, 命令只能从您的玩家对象发送,因此您无法控制其他玩家的对象。

BUT

Starting with Unity release 5.2 it is possible to send commands from non-player objects that have client authority. 从Unity版本5.2开始, 可以从具有客户端权限的非玩家对象发送命令 These objects must have been spawned with NetworkServer.SpawnWithClientAuthority or have authority set with NetworkIdentity.AssignClientAuthority. 必须使用NetworkServer.SpawnWithClientAuthority生成这些对象,或者使用NetworkIdentity.AssignClientAuthority设置权限。 Commands sent from these object are run on the server instance of the object, not on the associated player object for the client( more ). 从这些对象发送的命令在对象的服务器实例上运行,而不是在客户端的关联播放器对象上运行( 更多 )。

So what is the solution: Before sending the Command (or executing command function), Assign authority of that object to your Player . 那么解决方案是什么:在发送Command (或执行命令功能)之前, 将该对象的权限分配给您的Player Something like this 像这样的东西

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

" this " will be represent to your Player object. this ”将代表您的Player对象。 After making Command call you can remove authority using this code snippet. 进行Command调用后,您可以使用此代码段删除权限。

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

Again, " this " will be represent to your Player object. 同样,“ this ”将代表您的Player对象。

Important Note : I usually assign Authority of an object (If I want to use that) using OnTriggerEnter and remove authority on OnTriggerExit . 重要说明 :我通常使用OnTriggerEnter分配对象的权限(如果我想使用它)并删除OnTriggerExit的权限 It depend on specific scenario that at what event you want to acquire or remove an object authority. 它取决于您希望获取或删除对象权限的特定情况。

You can't send a command without local authority. 没有本地权限,您无法发送命令。

if (!isLocalPlayer) return;

But, what kind of data are you sending with this command ? 但是,您使用此命令发送了什么类型的数据? In general, and as you said : 一般而言,如你所说:

"it's state should be synchronized on server" “它的状态应该在服务器上同步”

So, IMHO, you have no reason to send a Command from your player. 所以,恕我直言,你没有理由从你的播放器发送Command Commands should be for player input. 命令应该是播放器输入。 These inputs will trigger actions in your game. 这些输入将触发游戏中的操作。 Your manager will get informations from these actions (score update, end of the game...) and send data and/or trigger actions on clients, using ClientRpc 您的经理将使用ClientRpc从这些操作获得信息(分数更新,游戏结束......)并在客户端上发送数据和/或触发操作

This is the server authority model. 这是服务器权限模型。 If you let a local object send commands, a hacker could easily come in and say to your manager 如果您让本地对象发送命令,黑客可以很容易地进入并告诉您的经理

"Hey, it's my turn. Hey, it's my turn again. Hey, my score is 9999999 and I won the game in 1 second.". “嘿,轮到我了。嘿,轮到我了。嘿,我的分数是9999999,我在1秒内赢了比赛。”

If You are using mirror then use Bypass Authority, took whole day to trying implement the above solutions which didn't work.如果您使用的是镜像,则使用绕过权限,花了一整天的时间来尝试实施上述无效的解决方案。 Here how it should be done: https://mirror-networking.gitbook.io/docs/guides/communications/remote-actions这里应该如何做: https : //mirror-networking.gitbook.io/docs/guides/communications/remote-actions

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM