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

时间:2015-09-03 19:09:56

标签: c# unity3d network-programming unity-networking

正如标题所示,我遇到的问题是客户端发送的命令没有被触发。

我正在尝试的基本功能是,当敌人在玩家面前并且我点击时,该玩家将暂时被击晕。如果我是主持人,工作正常,双方完全注册。

如果我正在扮演客户端,我会发现命令“应该”被发送,但我注意到我收到一条警告,上面写着“试图向非本地玩家发送命令”。同样,两端都没有任何结果。显然我必须在客户方面做错事,但不知道还有什么方法可以解决这个问题。

“问题”代码。

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

方法调用

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

编辑: 根据要求,完整地提到了两个脚本。

http://pastebin.com/mr4A9ZgH

http://pastebin.com/Qg0AjCCD

统一玩家配置:

https://gyazo.com/400c5b3a95c1a58f9b6e930b0c3c853b

https://gyazo.com/c17a7317767a00e2150ff34b03a03e8f

https://gyazo.com/322731aefbe69f9567d2b395523b8f2a

完整警告信息

  

尝试为非本地播放器发送命令。   UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter,   Int32,String)PlayerController:CallCmdStun()   ObjectInteractor:Update()(在Assets / Scripts / ObjectInteractor.cs:58)

4 个答案:

答案 0 :(得分:1)

我猜你正在gameobjectnetworkserver调出一个命令,或者该对象已经存在。无论如何,该对象不是您在playerprefab中分配的NetworkManager's SpawnInfo

那么,对于那些'Trying to send command for non-local player'的对象。您需要向NetworkIdentity 'Authority'提供[Command],以便他们致电NetworkIdentity.AssignClientAuthority(connectionToClient). 。并授予他们“权限”。你应该使用

NetworkIdentity.AssignClientAuthority

而且,事实[Command]可能只调用服务器。您需要'Player''AssignClientAuthority'上的其他 List<Map<String,String>> userDevices = clientdeviceService.getUserDevice(userId); List<String> selectedDevices = new ArrayList<String>(Arrays.asList(devices));//selectedDevices is------[stress0012,stress0014,] List<String> originalDevices = new ArrayList<String>(); List<String> originalDevicesRetain = new ArrayList<String>();//copy for operating for(Map<String,String> originalDevId : userDevices){ originalDevices.add(originalDevId.get("DEVID")); } originalDevicesRetain.addAll(originalDevices); originalDevicesRetain.retainAll(selectedDevices); //originalDevicesRetain now is [],and it return false. originalDevices.removeAll(originalDevicesRetain); if(!originalDevices.isEmpty()){ }

更多细节在这里:

Unity UNET - calling [Command] outside of player object

(我是中国人,所以也许我没有明确地表达myslef,希望你能理解。)

答案 1 :(得分:0)

确保您的播放器预制件上有一个NetworkIdentity组件,并选中了Local Player Authority。然后在问题代码之上,只有通过添加以下内容才能运行本地播放器:

if (!isLocalPlayer)
    return;

编辑:确保在Unity的播放器设置中包含UPID(在https://multiplayer.unity3d.com注册您的项目)(编辑 - &gt;项目设置 - &gt;播放器)如果您正在测试远程客户端,请在Cloud Project Id字段中。即使您使用的是localhost,远程客户端也会使用Unity的中继服务器连接到您的主机游戏。

编辑2 :尝试将通话更改为controller.CmdStun()controller.Stun()。然后在PlayerController中添加一个调用私有函数Stun()的公共函数CmdStun()

答案 2 :(得分:0)

您必须将脚本分配给OBJECT的根目录。我遇到了同样的问题。你必须考虑的限制很少。

  1. NetworkIdentity必须位于可生成预制件
  2. 的根游戏对象上
  3. NetworkBehaviour脚本必须与NetworkIdentity位于同一游戏对象上,而不是儿童游戏对象上
  4. 预制件无法在NetworkManager中注册,除非他们的根对象上有NetworkIdentity

答案 3 :(得分:0)

正如你所说:

  

警告说“尝试向非本地玩家发送命令”。

您可以将来自非玩家对象的命令发送为unity docs stated

  

命令从客户端上的玩家对象发送到玩家对象   在服务器上。为安全起见,命令只能从您的发送   玩家对象,所以你无法控制其他玩家的对象。

<强> BUT

  

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