Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Third Party [Photon] Transform not synching

Discussion in 'Multiplayer' started by mntoyi, Nov 6, 2020.

  1. mntoyi

    mntoyi

    Joined:
    Jan 9, 2018
    Posts:
    3
    Hey guys! Wonder if you could help me with this, I'm stuck and don't know what to do.
    I'm trying to make a 1vs1 bomberman game with a kick/throw bomb mechanic, the thing is that when playerA puts a bomb and kick it, it shows fine on both clients, but when playerB tries to return it, you can see the bomb going back on playerB screen but not on playerA.
    The bomb is spawned with

    Code (CSharp):
    1. PhotonNetwork.Instantiate("Bomb", position, Quaternion.identity);
    and has its PhotonView and TransformView attached.
    The player and bomb movement are tile based and made by Coroutines. Here's a video showing the issue.

    Video

    Here's the Player's kick code:

    Code (csharp):
    1.  
    2. private void ProcessActionInput()
    3.     {
    4.         if(Input.GetKeyDown(KeyCode.X))
    5.         {
    6.             RaycastHit2D hit = Physics2D.Raycast(transform.position, currentDirection, 2.0f, isBomb);
    7.             if (hit)
    8.             {
    9.                 Bomb bomb = hit.transform.GetComponent<Bomb>();
    10.                 if (bomb != null)
    11.                     bomb.StartCoroutine(bomb.MoveBomb(currentDirection));
    12.             }
    13.             else return;
    14.         }
    15.     }
    16.  
    And the Bomb move Coroutine:

    Code (csharp):
    1.  
    2. public IEnumerator MoveBomb(Vector3 direction)
    3.     {
    4.         coll.enabled = false;
    5.         IsMoving = true;
    6.  
    7.         float elapsedTime = 0.0f;
    8.         float distance = 0.0f;
    9.         float bombSpeed = 0.0f;
    10.         bool canJump = false;
    11.         origPos = transform.position;
    12.         Vector3 jumpDistance = origPos + direction;
    13.  
    14.         RaycastHit2D hit = Physics2D.Raycast(origPos, direction, 11.0f, canPhase);
    15.         if(hit)
    16.         {
    17.             if (direction == Vector3.up)
    18.             {
    19.                 distance = Mathf.Abs(origPos.y - hit.transform.position.y);
    20.                 targetPos = new Vector3(origPos.x, hit.transform.position.y - 1.0f, origPos.z);
    21.             }
    22.             else if (direction == Vector3.down)
    23.             {
    24.                 distance = Mathf.Abs(origPos.y - hit.transform.position.y);
    25.                 targetPos = new Vector3(origPos.x, hit.transform.position.y + 1.0f, origPos.z);
    26.             }
    27.             else if (direction == Vector3.right)
    28.             {
    29.                 distance = Mathf.Abs(origPos.x - hit.transform.position.x);
    30.                 targetPos = new Vector3(hit.transform.position.x - 1.0f, origPos.y, origPos.z);
    31.             }
    32.             else if (direction == Vector3.left)
    33.             {
    34.                 distance = Mathf.Abs(origPos.x - hit.transform.position.x);
    35.                 targetPos = new Vector3(hit.transform.position.x + 1.0f, origPos.y, origPos.z);
    36.             }
    37.             bombSpeed = distance / 8;
    38.         }
    39.  
    40.         if(distance <= 1.0f)
    41.         {
    42.             Collider2D occupiedTile;
    43.             distance = 0.0f;
    44.             while (distance < 11.0f)
    45.             {
    46.                 occupiedTile = Physics2D.OverlapCircle(jumpDistance, 0.25f, canJumpInto);
    47.                 if (occupiedTile != null)
    48.                 {
    49.                     distance += 1.0f;
    50.                     jumpDistance = origPos + (direction * distance);
    51.                     if (occupiedTile.gameObject.CompareTag("Boundary"))
    52.                     {
    53.                         canJump = false;
    54.                         break;
    55.                     }
    56.                 }
    57.                 else
    58.                 {
    59.                     canJump = true;
    60.                     break;
    61.                 }
    62.             }
    63.  
    64.             if (canJump)
    65.             {
    66.                 if (direction == Vector3.up)
    67.                     targetPos = new Vector3(origPos.x, origPos.y + distance, origPos.z);
    68.                 else if (direction == Vector3.down)
    69.                     targetPos = new Vector3(origPos.x, origPos.y - distance, origPos.z);
    70.                 else if (direction == Vector3.right)
    71.                     targetPos = new Vector3(origPos.x + distance, origPos.y, origPos.z);
    72.                 else
    73.                     targetPos = new Vector3(origPos.x - distance, origPos.y, origPos.z);
    74.                 bombSpeed = distance / 8;
    75.             }
    76.             else
    77.             {
    78.                 coll.enabled = true;
    79.                 IsMoving = false;
    80.                 yield break;
    81.             }
    82.         }
    83.        
    84.         coll.enabled = true;
    85.         while (elapsedTime < 1.0f)
    86.         {
    87.             transform.position = Vector3.Lerp(origPos, targetPos, elapsedTime);
    88.             elapsedTime += (Time.deltaTime / bombSpeed);
    89.             yield return null;
    90.         }
    91.  
    92.         transform.position = targetPos;
    93.         yield return null;
    94.         IsMoving = false;
    95.     }
    96.  
     
  2. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,732
    It's probably an ownership issue. When it's instantiated it belongs to the player that instantiated it, player A. So player B needs to request ownership before it can control it.
     
  3. mntoyi

    mntoyi

    Joined:
    Jan 9, 2018
    Posts:
    3
    Oh I see. I'll look into that, thanks!

    EDIT: it works now, thank you so much @Munchy2007!
    Is this a correct way to do it?
    Code (CSharp):
    1. if(Input.GetKeyDown(KeyCode.X))
    2.         {
    3.             RaycastHit2D hit = Physics2D.Raycast(transform.position, currentDirection, 2.0f, isBomb);
    4.             if (hit)
    5.             {
    6.                 Bomb bomb = hit.transform.GetComponent<Bomb>();
    7.                 if (bomb != null)
    8.                 {
    9.                     if (!bomb.Pv.AmOwner)
    10.                         bomb.ChangeOwner(pv.Owner);
    11.  
    12.                     bomb.StartCoroutine(bomb.MoveBomb(currentDirection));
    13.                 }
    14.             }
    15.             else return;
    16.         }
     
    Last edited: Nov 9, 2020
  4. tobiass

    tobiass

    Joined:
    Apr 7, 2009
    Posts:
    3,062
    When the object changes ownership, this has to be synced through via the network, so it's not "done" immediately.
    I don't see what exactly you do with bomb.ChangeOwner but maybe you are not "officially" the owner yet, in the coroutine you start right away.
    There should be a callback for the "done" ownership change. Start moving then, or multiple clients may think they are the owner of the obj.
     
  5. mntoyi

    mntoyi

    Joined:
    Jan 9, 2018
    Posts:
    3
    Thanks @tobiass for your answer.
    Would something like this do the trick? (It would be inside the coroutine before it starts moving):
    Code (CSharp):
    1. yield return new WaitUntil(() => "ownership done");
    Right now with the ownership change that I've made, it kinda works. But I'll look further into this, thank you again.