Unity:如何通过网络销毁游戏对象?

Unity: How to destroy a gameobject through network?

我们正在 Unity 上构建一个实时战略游戏,并试图通过网络销毁服务器和客户端上的游戏对象。 目前玩家可以随时销毁自己的对象,而服务器可以销毁所有对象。但是,当客户端试图销毁服务器(或其他客户端)的对象时,它只会在该客户端上被销毁。 (因为客户端既没有 hasAuthority 也没有对象 isLocalPlayer)

我们尝试了不同的方法:

1。使用销毁(游戏对象)

这显然行不通,因为它只会在本地被销毁。

2。使用 NetworkServer.Destroy(gameObject)

由于我们没有权限,所以失败了。

3。使用命令销毁对象

当我们尝试在销毁对象的服务器上调用命令时,也失败了。由于权限检查:

Trying to send command for object without authority.

4。先分配权限

我们尝试通过以下方式分配权限 GetComponent<NetworkIdentity>().AssignClientAuthority(connectionToClient); 但收到错误消息:

AssignClientAuthority can only be call on the server for spawned objects.

由于第 3 点,尝试在命令中执行此操作将失败。

还有其他方法可以销毁游戏对象吗? 销毁游戏对象的方法是什么?

编辑:我们在运行时(在命令中)通过 NetworkServer.SpawnWithClientAuthorityNetworkServer.Spawn

生成了大部分对象

如何使用 (1) 并设置每个客户端对自己的游戏对象拥有权限?那么您需要确保的是让服务器在特定事件时通知每个客户端。

Here 是一个关于多人游戏的更开放的问题,它描述了它如何手动工作。让客户端监听服务器 messages/RPCs.

尽管 UNet is going to end 很快(正如 Draco18s 已经提到的)到目前为止我会这样做:

  1. NetworkIdentity 添加到 GameObject 您希望能够通过网络 destroy/identify。

  2. 如果您生成的是预制件,请确保将其添加到 NetworkManager

  3. 中的可生成预制件中
  4. 由于本地播放器对象始终对自身和附加到它的组件具有权限,因此添加 [Command] 对本地播放器对象上的组件的调用(不在目标游戏对象上)并使用 NetworkServer.Destroy 例如像

    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;
    }
    
  5. 稍后在您的其他脚本中需要执行销毁的某个地方,您可以执行类似

    的操作
    // 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);
    

    无需先获取参考文献。

直接来自统一文档:

地方当局 本地权限(有时称为客户端权限)意味着本地客户端对特定的网络游戏对象具有权威控制权。这与默认状态形成对比,默认状态是服务器对网络游戏对象具有权威控制。

除了isLocalPlayer****,你还可以选择让player GameObjects拥有“local authority”。这意味着其所有者客户端上的玩家 GameObject 对其自身负责(或对其拥有权限)。这对于控制运动特别有用;这意味着每个客户端都有权决定如何控制他们自己的玩家游戏对象。

要在 GameObject 上启用本地玩家权限,请勾选 Network Identity 组件 的本地玩家权限复选框。 Network Transform 组件使用此“权限”设置,如果已设置,则将移动信息从客户端发送到其他客户端。

参见脚本API有关 NetworkIdentity 的参考文档 和 localPlayerAuthority 获取有关通过脚本实现本地玩家权限的信息。

see here

你只需要设置一些东西就可以了!