简体   繁体   English

UNET客户端无法发送服务器命令,主机可以

[英]UNET Client Cant Send Server Commands, Host Can

So as the title suggests, I'm having a problem where commands being sent by the client are not triggered. 因此,正如标题所示,我遇到的问题是客户端发送的命令不会被触发。

The basic functionality I'm trying to get working is that when an enemy is in front of the player and I click, that player will be momentarily stunned. 我正在努力工作的基本功能是,当敌人在玩家面前并且我点击时,该玩家将暂时被击晕。 Works fine if I'm host, and both sides perfectly register. 如果我是主持人,工作正常,双方完全注册。

If I'm playing as client, I get to the point where the command "should" be sent, but I notice I get a warning that says "Trying to send command for non-local player". 如果我正在扮演客户端,我会发现命令“应该”被发送,但我注意到我收到一条警告,上面写着“试图为非本地玩家发送命令”。 As well, nothing happens on either end. 同样,两端都没有任何结果。 Obviously I must be doing something wrong client side, but have no idea what other way to go about this. 显然我必须在客户端做错事,但不知道还有什么方法可以解决这个问题。

The "problem" code. “问题”代码。

            if (Input.GetButtonDown("Fire1")) {
            Ray ray = new Ray(transform.position, transform.forward);
            RaycastHit hit = new RaycastHit();
            Physics.Raycast(ray, out hit, 20f);
            if (hit.transform != null) {
                if (hit.rigidbody != null) {
                    PlayerController controller = hit.rigidbody.GetComponent<PlayerController>();
                    if (controller != null) {
                        if (!controller.stunned) {
                            // Send the stun command to the server
                            controller.CmdStun();
                        }
                    }
                }
            }
        }

The method calls 该方法调用

[Command]
public void CmdStun() {
    // Report that the stun was sent
    UnityEngine.Debug.Log("Stun Sent");
    RpcStun();
}

[ClientRpc]
public void RpcStun() {
    // Activate the stun timer.
    stunTimer.Start();
    // Track the players original color.
    normalColor = manager.color;
    // Make the players bot look like its shut down.
    manager.InitiateColorChange(Color.black);
    // Other code will check against this before trying to send another stun command.
    stunned = true;
}

Edit: Upon request heres the two scripts in their entirety. 编辑:根据请求继承完整的两个脚本。

http://pastebin.com/mr4A9ZgH http://pastebin.com/mr4A9ZgH

http://pastebin.com/Qg0AjCCD http://pastebin.com/Qg0AjCCD

Player configuration in unity: 玩家配置统一:

https://gyazo.com/400c5b3a95c1a58f9b6e930b0c3c853b https://gyazo.com/400c5b3a95c1a58f9b6e930b0c3c853b

https://gyazo.com/c17a7317767a00e2150ff34b03a03e8f https://gyazo.com/c17a7317767a00e2150ff34b03a03e8f

https://gyazo.com/322731aefbe69f9567d2b395523b8f2a https://gyazo.com/322731aefbe69f9567d2b395523b8f2a

Full Warning Message 完整的警告信息

Trying to send command for non-local player. 试图为非本地玩家发送命令。 UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter, Int32, String) PlayerController:CallCmdStun() ObjectInteractor:Update() (at Assets/Scripts/ObjectInteractor.cs:58) UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter,Int32,String)PlayerController:CallCmdStun()ObjectInteractor:Update()(在Assets / Scripts / ObjectInteractor.cs:58)

I guess you are calling a command on a gameobject you spawn by networkserver or the object has existed the scene already. 我猜你在networkserver gameobject产生的游戏对象上调用命令,或者对象已经存在于场景中。 Anyway, the object is not a playerprefab that you assign it in the NetworkManager's SpawnInfo . 无论如何,对象不是playerprefab您分配它在NetworkManager's SpawnInfo

So, for those Object that 'Trying to send command for non-local player' . 因此,对于那些'Trying to send command for non-local player' You need to give their NetworkIdentity a 'Authority' which enable them to call [Command] .And to give them 'Authority' you should use 你需要给他们的NetworkIdentity一个'Authority' ,使他们能够调用[Command] 。并给他们“权限”你应该使用

NetworkIdentity.AssignClientAuthority(connectionToClient).

And, as a fact NetworkIdentity.AssignClientAuthority may only call on a server. 而且,事实上NetworkIdentity.AssignClientAuthority可能只在服务器上调用。 You need an other [Command] on 'Player' to 'AssignClientAuthority' . 你需要'Player'上的其他[Command]指向'AssignClientAuthority'

More details are here: 更多细节在这里:

Unity UNET - calling [Command] outside of player object Unity UNET - 在玩家对象之外调用[Command]

(I'm a Chinese, so maybe I didn't express myslef clearly, hope you can understand.) (我是中国人,所以也许我没有清楚地表达myslef,希望你能理解。)

Be sure you have a NetworkIdentity component, with Local Player Authority checked, on your player prefab. 确保在播放器预制件上有一个NetworkIdentity组件,并选中了Local Player Authority。 Then above the problem code, only run it if it's the local player by adding the following: 然后在问题代码上方,只有通过添加以下内容才能运行本地播放器:

if (!isLocalPlayer)
    return;

EDIT: Be sure to include the UPID (from registering your project at https://multiplayer.unity3d.com ) in Unity's Player settings (Edit -> Project Settings -> Player) in the Cloud Project Id field if you're testing remote clients. 编辑:如果您正在测试远程,请务必在Cloud项目ID设置的Unity设置(编辑 - >项目设置 - >播放器)中包含UPID(从https://multiplayer.unity3d.com上注册您的项目)客户端。 Even if you're using localhost, the remote client uses Unity's relay server to connect to your host game. 即使您使用的是localhost,远程客户端也会使用Unity的中继服务器连接到您的主机游戏。

EDIT 2: Try changing the call to controller.CmdStun() to controller.Stun() . 编辑2:尝试将对controller.CmdStun()的调用更改为controller.Stun() Then in PlayerController add a public function Stun() that calls private function CmdStun() . 然后在PlayerController添加一个调用私有函数CmdStun()的公共函数Stun() CmdStun()

You must assign script to the root of the OBJECT. 您必须将脚本分配给OBJECT的根目录。 I was Having same problem. 我遇到了同样的问题。 There are few constrains you must consider. 您必须考虑的限制很少。

  1. A NetworkIdentity must be on the root game object of a spawnable prefab NetworkIdentity必须位于可生成预制件的根游戏对象上
  2. NetworkBehaviour scripts must be on the same game object as the NetworkIdentity, not on child game objects NetworkBehaviour脚本必须与NetworkIdentity位于同一游戏对象上,而不是与子游戏对象相同
  3. Prefabs can't be registered with the NetworkManager unless they have a NetworkIdentity on their root object 除非在根对象上具有NetworkIdentity,否则无法在NetworkManager中注册预制件

As you said: 如你所说:

warning that says "Trying to send command for non-local player". 警告说“试图为非本地玩家发送命令”。

You can send commands from non-player objects as unity docs stated : 您可以按照统一文档说明从非玩家对象发送命令:

Commands are sent from player objects on the client to player objects on the server. 命令从客户端上的播放器对象发送到服务器上的播放器对象。 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. 从这些对象发送的命令在对象的服务器实例上运行,而不是在客户端的关联播放器对象上运行。

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

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