5

因此,正如标题所示,我遇到了客户端发送的命令未被触发的问题。

我正在尝试使用的基本功能是,当敌人在玩家面前并且我点击时,该玩家会暂时被击晕。如果我是主持人,效果很好,并且双方都完美注册。

如果我作为客户端玩,我会到达“应该”发送命令的地步,但我注意到我收到一条警告,上面写着“尝试为非本地玩家发送命令”。同样,两端都没有发生任何事情。显然,我必须在客户端做错事,但不知道还有什么其他方法可以解决这个问题。

“问题”代码。

            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

4 回答 4

2

您必须将脚本分配给 OBJECT 的根。我有同样的问题。您必须考虑的限制很少。

  1. NetworkIdentity 必须位于可生成预制件的根游戏对象上
  2. NetworkBehaviour 脚本必须与 NetworkIdentity 在同一个游戏对象上,而不是在子游戏对象上
  3. Prefabs 不能在 NetworkManager 中注册,除非它们的根对象上有 NetworkIdentity
于 2016-07-22T18:26:59.177 回答
1

gameobject我猜你是在你生成的对象上调用命令,networkserver或者对象已经存在于场景中。无论如何,该对象不是playerprefab您在NetworkManager's SpawnInfo.

所以,对于那些'Trying to send command for non-local player'. 你需要给他们NetworkIdentity一个'Authority'使他们能够打电话[Command]的。并且给他们'权威'你应该使用

NetworkIdentity.AssignClientAuthority(connectionToClient).

而且,事实上NetworkIdentity.AssignClientAuthority可能只在服务器上调用。你需要另一个[Command]'Player''AssignClientAuthority'

更多详情在这里:</p>

Unity UNET - 在播放器对象之外调用 [Command]

(我是中国人,所以可能我表达的不是很清楚,希望你能理解。)

于 2016-06-02T05:07:56.803 回答
0

确保您的播放器预制件上有一个 NetworkIdentity 组件,并检查了本地播放器权限。然后在问题代码上方,仅当它是本地播放器时才运行它,方法是添加以下内容:

if (!isLocalPlayer)
    return;

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

编辑 2:尝试将呼叫更改controller.CmdStun()controller.Stun(). 然后PlayerController添加一个Stun()调用私有函数的公共函数CmdStun()

于 2015-09-03T20:19:20.317 回答
0

如你所说:

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

您可以按照统一文档所述从非玩家对象发送命令:

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

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

于 2017-03-31T07:43:29.607 回答