正如标题所示,我遇到的问题是客户端发送的命令没有被触发。
我正在尝试的基本功能是,当敌人在玩家面前并且我点击时,该玩家将暂时被击晕。如果我是主持人,工作正常,双方完全注册。
如果我正在扮演客户端,我会发现命令“应该”被发送,但我注意到我收到一条警告,上面写着“试图向非本地玩家发送命令”。同样,两端都没有任何结果。显然我必须在客户方面做错事,但不知道还有什么方法可以解决这个问题。
“问题”代码。
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;
}
编辑: 根据要求,完整地提到了两个脚本。
统一玩家配置:
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)
答案 0 :(得分: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'
上的其他 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的根目录。我遇到了同样的问题。你必须考虑的限制很少。
答案 3 :(得分:0)
正如你所说:
警告说“尝试向非本地玩家发送命令”。
您可以将来自非玩家对象的命令发送为unity docs stated:
命令从客户端上的玩家对象发送到玩家对象 在服务器上。为安全起见,命令只能从您的发送 玩家对象,所以你无法控制其他玩家的对象。
<强> BUT 强>
从Unity版本5.2开始,可以从中发送命令 具有客户端权限的非玩家对象。这些对象必须具有 已经使用NetworkServer.SpawnWithClientAuthority生成或拥有 使用NetworkIdentity.AssignClientAuthority设置的权限。命令 从这些对象发送的是在对象的服务器实例上运行的, 不在客户的关联玩家对象上。