客户端不在Unet中执行命令

编辑

好的,所以我通过在胶囊中添加一个刚体元件来部分解决了这个问题。 我读了一个地方,显然你必须有一个为了移动服务器。

问题2

接下来的问题是,我现在可以移动一个由客户产生的胶囊,主机可以随意移动胶囊多次。 现在我得到的问题是,当主机产生一个胶囊客户端不能移动它,我得到了一种客户端故障的影响,胶囊仍然不会在主机端移动。 为什么只有一种方式,而不是相反呢? 我首先想到的可能是Spawn vs SpawnWithClientAuthority,但这似乎没有什么区别。


项目总结

我有一个非常简单的多人游戏项目,我想要做的只有一个玩家主机,另一个作为客户端join。 一旦它们结合在一起,两个玩家可以产生一个胶囊,然后当用户点击胶囊时。 他们应该能够把它拿起来,在场景中移动,另一个玩家应该能够看到这个动作。 我可以让两个玩家连接到服务器并产生他们自己的胶囊,双方玩家都可以看到。 移动脚本也完成了。 但是,它只在主机端传输。 当客户端拿起对象时,它不会在服务器上更新。

问题

我已经做了一些debugging,发现当我在客户端调用这个命令时,它根本不是通过换行符和简单的debugging语句来执行的。

public void OnInputClicked(InputClickedEventData eventData) { Debug.Log("clicked"); if (isLocalPlayer) { if (Physics.Raycast(transform.position, direction: transform.forward, hitInfo: out hit, maxDistance: range)) { Debug.Log("Hit capsule"); objectID = GameObject.Find(hit.transform.name); objNetId = objectID.GetComponent<NetworkIdentity>(); playerIDThatClicked = player.GetComponent<NetworkIdentity>(); CmdAssignAuthority(objNetId, playerIDThatClicked); Debug.Log("grabbed"); } else { //if we are releasing the object we want to unassign our authority if (objNetId != null) { CmdAssignAuthority(objNetId, playerIDThatClicked); objNetId = null; Debug.Log("released"); } } } } [Command] void CmdAssignAuthority(NetworkIdentity target, NetworkIdentity player) { Debug.Log("inside cmd"); current = target.clientAuthorityOwner; playerconn = player.connectionToClient; if (current != null && current != playerconn) { Debug.Log("Had authority now removing and replacing"); target.RemoveClientAuthority(current); target.AssignClientAuthority(playerconn); } else if (current != null) { Debug.Log("removing authority"); target.RemoveClientAuthority(current); } else if (current == null) { Debug.Log("No authority, adding one now"); target.AssignClientAuthority(playerconn); } else { Debug.Log("CmdAuthority error"); target.RemoveClientAuthority(playerconn); } } 

我是否正确地调用这个命令? 该脚本附加到玩家预制件上,并且胶囊预制件包含networkingID和networking变换。 我对Unet来说很新,这感觉就像一个noob错误。

编辑:

如果你的对象有相同的名字,我可以看到GameObject.find(hit.transform.name)给你的问题(改用hit.transform.gameObject


原始答案:

如果我正在读你的逻辑权限, CmdAssignAuthority另一种写法如下:

  • if (current != null && current != connectionToClient)将权限设置为connectionToClient
  • else if ( current == connectionToClient )设置为null (b / c current!= null意味着由于第一个if语句,它必须连接到客户端)
  • else if ( current == null )设置为connectionToClient

我不能完全确定你的OnInputClicked多lessOnInputClicked因为AR设备之间的差异,但我将假设像这样的video 。 OnInputClicked的逻辑可以被编码为:

  • if ( click and raycast hit )它会做这个对象的上述例程
  • if ( click and miss and cached hit object )它将执行相同的例程

这个逻辑有一些潜在的错误:

  • 用相同的光线投射结果(​​击中或未命中)点击两次会使权威与实际点击不同步(命中将是释放,而命中将设置权限)。
  • 因为它只是向connectionToClient分配权限,所以主机客户端在点击的时候也会把权限分配给connectionToClient ,这也许就是为什么你永远不能在主机上移动它。
  • 第三种情况在你的CmdAssignAuthority ,你的第一个if捕获不应该发生,使更难阅读正在发生的事情。

它看起来像你的逻辑纠结在CmdSetAuthority并且如果OnInputClicked不是connectionToClient ,可能会在OnInputClicked分解。 我建议重写你的逻辑,以便发送点击播放器的某种ID到CmdSetAuthority而不是在nullconnectionToClient之间切换