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

时间:2018-11-06 15:22:30

标签: unity3d multiplayer game-development

我们正在Unity上构建实时策略游戏,并尝试通过网络销毁服务器和客户端上的游戏对象。 当前,玩家可以始终销毁自己的对象,而服务器可以销毁所有对象。但是,当客户端尝试销毁服务器(或其他客户端)的对象时,它只会在此客户端上销毁。 (由于客户端既没有Authority也没有对象isLocalPlayer)

我们尝试了不同的方法:

1。使用Destroy(gameObject)

这显然不起作用,因为它只能在本地销毁。

2。使用NetworkServer.Destroy(gameObject)

此操作失败,因为我们没有权限。

3。使用命令销毁对象

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

  

试图未经授权就发送对象命令。

4。首先分配权限

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

  

只能在服务器上为生成的对象调用AssignClientAuthority。

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

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

编辑:我们在运行时(通过命令)通过NetworkServer.SpawnWithClientAuthorityNetworkServer.Spawn产生了大多数对象

3 个答案:

答案 0 :(得分:1)

尽管事实UNet is going to end很快(如Draco18s所述),到目前为止我还是会这样做:

  1. 向要通过网络销毁/识别的NetworkIdentity添加GameObject

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

  3. 中可生成的预制件中
  4. 由于本地播放器对象始终具有对自身及其连接组件的权限,因此将[Command]调用添加到本地播放器对象上的组件 (不在目标上) GameObjects),并使用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);
    

    无需先获取参考。

答案 1 :(得分:0)

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

Here是关于多人游戏的一个开放性问题,描述了它如何手动工作。通过让客户端监听服务器消息/ RPC。

答案 2 :(得分:0)

直接来自统一文档:

地方当局 本地权限(有时称为客户端权限)是指本地客户端对特定的联网GameObject具有权威控制权。这与默认状态相反,默认状态是服务器对网络游戏对象具有权威控制。

除了isLocalPlayer ****,您还可以选择使玩家GameObjects具有“本地权限”。这意味着,其所有者客户端上的玩家GameObject对其自身负责(或拥有权限)。这对于控制运动特别有用;这意味着每个客户端都有权控制自己的玩家GameObject的控制方式。

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

请参阅有关NetworkIdentity的Scripting API参考文档  和localPlayerAuthority获取有关通过脚本实现本地播放器权限的信息。

see here

您只需要进行一些设置,就可以了!