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

本文关键字:主机 命令 服务器 客户端 不能 UNET | 更新日期: 2023-09-27 18:11:16

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

我想要实现的基本功能是,当敌人出现在玩家面前而我点击时,玩家将被暂时击昏。如果我是主持人就行了,而且双方都能很好地登记。

如果我作为客户端玩,我到达命令"应该"发送的点,但我注意到我得到一个警告,说"试图为非本地玩家发送命令"。同样,两端都没有任何反应。显然,我一定是在客户端做错了什么,但不知道还有什么其他方法可以解决这个问题。

问题代码。

            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

unity中的玩家配置:

https://gyazo.com/400c5b3a95c1a58f9b6e930b0c3c853b

https://gyazo.com/c17a7317767a00e2150ff34b03a03e8f

https://gyazo.com/322731aefbe69f9567d2b395523b8f2a

完整警告信息

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

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

必须将script分配给OBJECT的根目录。我也有同样的问题。你必须考虑一些限制条件。

  1. NetworkIdentity必须在可生成预制的根游戏对象上
  2. NetworkBehaviour脚本必须与NetworkIdentity在同一个游戏对象上,而不是在子游戏对象上
  3. prefab不能注册到NetworkManager,除非他们有一个NetworkIdentity在他们的根对象

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

所以,对于那些对象,'Trying to send command for non-local player'。你需要给他们的NetworkIdentity一个'Authority',这样他们就可以调用[Command]。要给他们"权限",你应该使用

NetworkIdentity.AssignClientAuthority(connectionToClient).

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

更多细节在这里:

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

(我是一个中国人,所以可能我没有表达清楚,希望你能理解)

确保在播放器预制件上有一个NetworkIdentity组件,并选中了Local Player Authority。然后在问题代码上面,只有当它是本地播放器时才运行它,添加以下内容:

if (!isLocalPlayer)
    return;

EDIT:一定要包括UPID(从注册你的项目https://multiplayer.unity3d.com)在Unity的播放器设置(编辑->项目设置->播放器)在云项目Id字段,如果你测试远程客户端。即使你使用的是本地主机,远程客户端也会使用Unity的中继服务器连接到你的主机游戏。

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

如你所说:

提示"尝试为非本地播放器发送命令"。

你可以从非玩家对象发送命令,如unity文档所述:

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

从Unity发布5.2开始,可以从具有客户端权限的非玩家对象。这些物体必须有由NetworkServer派生。SpawnWithClientAuthority或have使用NetworkIdentity.AssignClientAuthority设置权限。命令从这些对象发送的消息在该对象的服务器实例上运行,