Unity:如何通过网络销毁游戏对象?
Posted
技术标签:
【中文标题】Unity:如何通过网络销毁游戏对象?【英文标题】:Unity: How to destroy a gameobject through network? 【发布时间】:2019-04-10 00:30:55 【问题描述】:我们正在 Unity 上构建实时战略游戏,并尝试通过网络破坏服务器和客户端上的游戏对象。 目前玩家可以随时销毁自己的物品,服务器可以销毁所有物品。但是,当客户端尝试销毁服务器(或其他客户端)的对象时,它只会在该客户端上被销毁。 (因为客户端既没有权限也没有对象是LocalPlayer)
我们尝试了不同的方法:
1。使用 Destroy(gameObject)
这显然行不通,因为它只会在本地被销毁。
2。使用 NetworkServer.Destroy(gameObject)
这失败了,因为我们没有权限。
3。使用命令销毁对象
当我们尝试在我们销毁对象的服务器上调用命令时也会失败。由于权限检查:
试图在没有权限的情况下为对象发送命令。
4。首先分配权限
我们试图通过
GetComponent<NetworkIdentity>().AssignClientAuthority(connectionToClient);
但得到错误消息:
AssignClientAuthority 只能在服务器上调用生成对象。
由于第 3 点,尝试在命令中执行此操作将失败。
还有其他方法可以销毁游戏对象吗? 销毁游戏对象的方法是什么?
编辑:我们在运行时(在命令中)通过NetworkServer.SpawnWithClientAuthority
或NetworkServer.Spawn
生成了大部分对象
【问题讨论】:
您是否使用NetworkServer.Spawn
创建您要删除的对象?
告诉服务器销毁任何东西。实际上,这个问题是我不喜欢 UNet 的原因之一,也是 Unity 弃用它并重新开始的原因之一。
@Draco18s Unity 真的弃用 uNet?
@Programmer 是的。 support.unity3d.com/hc/en-us/articles/…
不知道。就在我真正学习它的过程中,它被弃用了……对于 OP,我建议你使用 Photon。它已经存在很长时间了,我认为它不会很快消失。
【参考方案1】:
如何使用 (1) 并将每个客户端设置为对自己的游戏对象具有权限?那么您需要确保的就是让服务器在特定事件上通知每个客户端。
Here 是一个关于多人游戏的开放式问题,描述了它如何手动工作。通过让客户端监听服务器消息/RPC。
【讨论】:
【参考方案2】:尽管UNet is going to end 很快(正如 Draco18s 已经提到的那样)到目前为止我会这样做:
将NetworkIdentity
添加到您希望能够通过网络销毁/识别的GameObject
。
如果它是您生成的预制件,请确保将其添加到 NetworkManager
中的可生成预制件中
由于本地玩家对象始终拥有对其自身和附加组件的权限,因此将[Command]
调用添加到本地玩家对象(而不是目标游戏对象)上的组件并使用@ 987654322@ 例如像
public class NetworkObjectDestroyer : NetworkBehaviour
// Called by the Player
[Client]
public void TellServerToDestroyObject(GameObject obj)
CmdDestroyObject(obj);
// Executed only on the server
[Command]
private void CmdDestroyObject(GameObject obj)
// It is very unlikely but due to the network delay
// possisble that the other player also tries to
// destroy exactly the same object beofre the server
// can tell him that this object was already destroyed.
// So in that case just do nothing.
if(!obj) return;
NetworkServer.Destroy(obj);
提示:您也可以添加它以便于访问,因为您确定您只需要访问其中一个组件(即您的本地播放器):
public static NetworkObjectDestroyer Instance;
private void Awake()
// skip if not the local player
if(!isLocalPlayer) return;
// set the static instance
Instance = this;
稍后在需要执行破坏的其他脚本中的某个地方执行类似的操作
// that you would have to get somewhere if not anyway
// calling from a component of the local player object
GameObject playerObject;
// wherever you get your target object from
GameObject targetObject;
playerObject.GetComponent<NetworkObjectDestroyer>().TellServerToDestroyObject(targetObject);
如果你之前添加了静态实例会更容易。比你可以简单地使用
NetworkObjectDestroyer.Instance.TellServerToDestroyObject(targetObject);
无需先获取参考资料。
【讨论】:
这实际上不是我们希望的答案。但是使用另一个 SyncVar,我们能够成功地实施这种方法。【参考方案3】:直接来自统一文档:
地方当局 本地权限(有时称为客户端权限)意味着本地客户端对特定的联网游戏对象具有权威控制。这与服务器对联网游戏对象具有权威控制的默认状态形成对比。
除了isLocalPlayer****,你可以选择让玩家GameObjects拥有“本地权限”。这意味着其所有者客户端上的玩家 GameObject 对其自身负责(或对其拥有权限)。这对于控制运动特别有用;这意味着每个客户端都有权控制自己的玩家 GameObject 的控制方式。
要在 GameObject 上启用本地玩家权限,请勾选 Network Identity 组件 的本地玩家权限复选框。 Network Transform 组件使用此“权限”设置,如果设置了此设置,则将移动信息从客户端发送到其他客户端。
请参阅有关 NetworkIdentity 的脚本 API 参考文档 和 localPlayerAuthority 获取有关通过脚本实现本地玩家权限的信息。
see here
您只需要设置一些东西就可以了!
【讨论】:
以上是关于Unity:如何通过网络销毁游戏对象?的主要内容,如果未能解决你的问题,请参考以下文章
Unity (C#) - 如何在销毁/重生系统中挑选出被 Raycast 检测到的 GameObject