How to properly delete an object over the network?

So, I spent more than a week studying the crooked documentation, which is not clear for whom it was written, and everything that is written there does not work or works, to put it mildly, crooked.

My project is a 2D game with procedural level generation. There are players and enemies that fire bullets. These bullets are supposed to destroy themselves and the object they hit. I tried many options on how to do this, but I got a lot of errors related to deleting objects over the network.

All objects in the game scene spawn PhotonNetwork.Instantiate and have a PhotonView component.

At the moment, in order for everything to work, I delete the object like this:

private void OnTriggerEnter2D(Collider2D coll)

  {

    if (coll.CompareTag("Player") || coll.CompareTag("Enemy") || coll.CompareTag("GameWall") || coll.CompareTag("swall") || coll.CompareTag("bwall"))

    {

      gameObject.SetActive(false);

      Destroy(gameObject, 2f);

    }

  }

and it only works if one client is running. If you run two or more clients, then it does not work well. Deleting objects is not synchronized on all clients.

How to delete an object that belongs or does not belong to the client on which it is deleted?

Comments

  • a week studying the crooked documentation

    Oh, thanks.

    Your approach won't work because you network instantiate an object (PhotonNetwork.Instantiate) but destroy it locally (GameObject.Destroy). To sync that objects got destroyed, you need to use PhotonNetwork.Destroy. PhotonNetwork.Destroy is explained in context of PhotonNetwork.Instantiate.

  • That said, you may want to rethink destroying the object due to collision. As there is lag and all players control a part of the networked world, everyone's view on the current scene / situation will differ a little. Only one client should make the decision to network destroy the object in question. In your code, any networked player will try to destroy the object and this will cause issues.

    You may want to look into Fusion, where a single Host / Server is running the simulation with everyone's input. Others may locally destroy objects at will but the actual simulation is done on one instance and it updates everyone else (and overrides the networked simulation of other clients).

  • To sync that objects got destroyed, you need to use PhotonNetwork.Destroy. PhotonNetwork.Destroy

    I used it.

    But then I get errors from other clients that they cannot delete the object over the network. Because they are not the master client or the owner of the object.

    I studied the material that is written at your link before creating my post. And that confused me even more.

    I need to delete an object that was created by a client using PhotonNetwork.Instantiate and tell other clients to delete this object too

    To do this, I used RPC

    photonView.RPC("DelBrick", RpcTarget.AllViaServer);
    
    [PunRPC]
        public void DelBrick()
        {
            //PhotonNetwork.Destroy(gameObject);
            gameObject.SetActive(false);
            Destroy(gameObject, .5f);
        }
    

    but if i uncomment //PhotonNetwork.Destroy(gameObject); and comment out other lines, I get errors from other clients.

    So how to make it work and not get errors?




  • In best case, the owner / controller of an object should destroy it. Otherwise, a remote player destroyed the object already but the controller is still sending updates.

    If the controller of the object can't decide when to destroy the object, you need to send an RPC to the controller, who then should use PhotonNetwork.Destroy(), which will tell everyone else the object is gone.