Search Unity

Third Party Synchronization of object destruction in photon

Discussion in 'Multiplayer' started by Hatemsla, Jul 25, 2022.

  1. Hatemsla

    Hatemsla

    Joined:
    Oct 17, 2021
    Posts:
    62
    I need to somehow synchronize the destruction of walls, or rather fragments of the wall. Each wall has a PhotonView, which is why all players will spawn synchronously, but the problem is that the wall has fragments, destroying which a passage is formed and the player can drive, the only solution I could come up with so far is to attach PhotonView fragments, but as far as I understand it is extremely resource-intensive. How can I do better? It's just that the player shoots a beam into the wall and a tag check occurs, and then the fragment is destroyed, just how to send an RPC or RaiseEvent for this?
    Code (CSharp):
    1. public override void Shoot()
    2.     {
    3.         NextFire = 0;
    4.         RaycastHit hit;
    5.         if (Physics.Raycast(ShootPoint.position, ShootPoint.forward, out hit, Range, mask, QueryTriggerInteraction.Ignore))
    6.         {
    7.             StartCoroutine(ShotEffect());
    8.             Laser.startColor = Color.red;
    9.             Laser.endColor = Color.red;
    10.             Laser.SetPosition(0, ShootPoint.position);
    11.             Laser.SetPosition(1, ShootPoint.position + ShootPoint.forward * hit.distance);
    12.             if (hit.transform.tag == "Wall")
    13.             {
    14.                 Destroy(hit.transform.gameObject);
    15.             }
    16.             if (hit.transform.gameObject.layer == 3)
    17.             {
    18.                 var car = hit.transform.GetComponentInParent<Rigidbody>();
    19.                 StartCoroutine(SlowCar(car));
    20.             }
    21.         }
    22.         else
    23.         {
    24.             StartCoroutine(ShotEffect());
    25.             Laser.startColor = Color.red;
    26.             Laser.endColor = Color.red;
    27.             Laser.SetPosition(0, ShootPoint.position);
    28.             Laser.SetPosition(1, ShootPoint.position + ShootPoint.forward * Range);
    29.         }
    30.     }
    Code (CSharp):
    1. private void Update()
    2.     {
    3.         ShowPlaces();
    4.         if (_photonView.IsMine)
    5.         {
    6.             if(Input.GetKeyDown(KeyCode.Q) && _playerGun.NextFire >= _playerGun.FireRate)
    7.                 _playerGun.Shoot();
    8.                
    9.             PositionControl();
    10.             ReloadControl();
    11.         }
    12.     }
     
  2. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,066
    Do you need to support late joining?
    If not, just come up with IDs for all fragments and send them via RaiseEvent or RPC.
    If there are plenty of fragments, you could update everyone else in a certain frequency (e.g. 10-20x per sec) while shooting. This means you would not send a message per destroyed fragment but have a list of them. Or send something like a range of IDs of destroyed fragments.
     
  3. Hatemsla

    Hatemsla

    Joined:
    Oct 17, 2021
    Posts:
    62
    The bottom line is that any player or bot can spawn the walls with the condition that he is the first in the race, I have already added PhotonView to them and tried to spawn them through PhotonNetwork.Instantiate, but it doesn't work, that is, each client has duplicate walls, while the local ones are placed correctly, and the walls of the other client are placed at the origin. In the list where I store wall objects, some of the elements do not have a link because they are from another client. I also need the function to be run only by the main client and at the same time synchronized with other players.
     
  4. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,066
    So the first in race can spawn walls? Are those anywhere or in fixed places in the scene? The difference being: You could give each an ID / number, when they are in the scene anyways. Then it makes sense to send activation via RaiseEvent.
    If they are not pre-defined, you would have to instantiate them or you could send an event telling everyone to place a wall at pos x,y,z. This works OK if nobody is joining late anyways.

    You can run code on a single client in a room by using the Master Client. This is not a special client as such but only one client per room is the Master Client, so that helps run code only once in a room. Put that code in Update() and make it a block with the condition PhotonNetwork.IsMasterClient. Sync via RaiseEvent or RPC.

    There is always some lag between doing something on the Master Client and everyone else seeing this on their end. This is the tricky part of multiplayer game dev.
     
    Munchy2007 likes this.
  5. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,735
    This is one of the tricky parts of multiplayer game dev ;)
     
    tobiass likes this.