Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question Objects out of sync with photon view

Discussion in 'Multiplayer' started by ASDF_alpha, Dec 26, 2023.

  1. ASDF_alpha

    ASDF_alpha

    Joined:
    Aug 25, 2020
    Posts:
    29
    I am making a game - some sort of football game for two players multiplayer, the ball bounces off the screen and players, but it's always out of sync for the second player(the green one) example images(I put a ruler there from screenshot to show the difference in position:
    upload_2023-12-26_11-8-14.png upload_2023-12-26_11-8-16.png upload_2023-12-26_11-8-17.png
    it looks thetball is a bit out of sync(possibly player too), these images are taken from a video i recorded of the gameplay.
    I am using Photon Transform View to sync the objects, red player is masterclient and is controlled by it's client only, ball is only controlled by masterclient and green player is only controlled by it's own client, all movements are then synced with the photon transform view.All movements are not done by physics and are done by using transform.translate and rotate.

    The players are instantiated into the scene and the ball is a scene object.
    When in the green player's client, the ball doesn't bounce off when colliding with green, as the positions are out of sync, but it all functions normally in red player's client. The ball does bounce off the green player when it collides with the green player in red's client though, I think it's due to the ball being controlled on MasterClient and positions of players and ball are a bit out of sync.

    Does anyone have any idea on how I can fix this?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5.  
    6. public class Ball : MonoBehaviour
    7. {
    8.     [SerializeField] private float m_speed;
    9.     [SerializeField] private float maxY;
    10.     [SerializeField] private float minY;
    11.     [SerializeField] private float minX;
    12.     [SerializeField] private float maxX;
    13.     [SerializeField] private PhotonView pv;
    14.     [SerializeField] private float rotateSpeed;
    15.     [SerializeField] private Transform GFX;
    16.  
    17.     private Vector2 movDir;
    18.     private GameManager gm;
    19.  
    20.     private void Start()
    21.     {
    22.         if(!PhotonNetwork.IsMasterClient)
    23.         {
    24.             return;
    25.         }
    26.  
    27.         gm = GameObject.FindGameObjectWithTag("GameManager").GetComponent<GameManager>();
    28.         movDir = new Vector2(1, 1).normalized;
    29.     }
    30.  
    31.     // Update is called once per frame
    32.     void Update()
    33.     {
    34.         if (!PhotonNetwork.IsMasterClient)
    35.         {
    36.             return;
    37.         }
    38.  
    39.         if (gm.canMove)
    40.         {
    41.             if (transform.position.x <= minX)
    42.             {
    43.                 transform.position = new Vector2(minX, transform.position.y);
    44.                 movDir *= new Vector2(-1, 1);
    45.             }
    46.  
    47.             if (transform.position.x >= maxX)
    48.             {
    49.                 transform.position = new Vector2(maxX, transform.position.y);
    50.                 movDir *= new Vector2(-1, 1);
    51.             }
    52.  
    53.             if (transform.position.y >= maxY)
    54.             {
    55.                 transform.position = new Vector2(transform.position.x, maxY);
    56.                 movDir *= new Vector2(1, -1);
    57.             }
    58.  
    59.             if (transform.position.y <= minY)
    60.             {
    61.                 transform.position = new Vector2(transform.position.x, minY);
    62.                 movDir *= new Vector2(1, -1);
    63.             }
    64.             transform.Translate(movDir * m_speed * Time.deltaTime);
    65.         }
    66.         GFX.Rotate(new Vector3(0, 0, rotateSpeed * Time.deltaTime));
    67.  
    68.     }
    69.  
    70.     private void OnTriggerEnter2D(Collider2D col)
    71.     {
    72.         if(PhotonNetwork.IsMasterClient)
    73.         {
    74.             if (col.CompareTag("Player"))
    75.             {
    76.                 if (col.GetComponent<Player>().moveDir.x != 0 || col.CompareTag("Player") && col.GetComponent<Player>().moveDir.y != 0)
    77.                 {
    78.                     movDir = col.GetComponent<Player>().moveDir;
    79.                 }
    80.                 else
    81.                 {
    82.                     movDir = -movDir;
    83.                 }
    84.             }
    85.  
    86.             switch (col.gameObject.tag)
    87.             {
    88.                 case "Player1Goal":
    89.                     gm.AddScore("player2");
    90.                     break;
    91.                 case "Player2Goal":
    92.                     gm.AddScore("player1");
    93.                     break;
    94.             }
    95.         }
    96.     }
    97. }
    98.  
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5. using UnityEngine.UI;
    6.  
    7. public class Player : MonoBehaviour
    8. {
    9.  
    10.     [SerializeField] private float m_Speed;
    11.     [SerializeField] private float maxY;
    12.     [SerializeField] private float minY;
    13.     [SerializeField] private float minX;
    14.     [SerializeField] private float maxX;
    15.     [SerializeField] private Transform GFX;
    16.     [SerializeField] private Slider healthSlider;
    17.     [SerializeField] private PhotonView pv;
    18.  
    19.     public Vector3 spawnPoint;
    20.     public Vector2 moveDir;
    21.     public int health;
    22.     public int opponentNumber;
    23.  
    24.     private GameManager gm;
    25.  
    26.     private void Start()
    27.     {
    28.         healthSlider.maxValue = health;
    29.         gm = GameObject.FindGameObjectWithTag("GameManager").GetComponent<GameManager>();
    30.  
    31.         if(opponentNumber != 1 && opponentNumber != 2)
    32.         {
    33.             Player opponent;
    34.             for (int i = 0; i < GameObject.FindGameObjectsWithTag("Player").Length; i++)
    35.             {
    36.                 if(GameObject.FindGameObjectsWithTag("Player")[i] != this.gameObject)
    37.                 {
    38.                     opponent = GameObject.FindGameObjectsWithTag("Player")[i].GetComponent<Player>();
    39.  
    40.                     switch (opponent.opponentNumber)
    41.                     {
    42.                         case 1:
    43.                             opponentNumber = 2;
    44.                             break;
    45.                         case 2:
    46.                             opponentNumber = 1;
    47.                             break;
    48.                     }
    49.                 }
    50.             }
    51.         }
    52.     }
    53.  
    54.     // Update is called once per frame
    55.     void Update()
    56.     {
    57.         if (pv.IsMine)
    58.         {
    59.             if(gm.canMove)
    60.             {
    61.                 #region player movement
    62.                 moveDir = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")).normalized;
    63.  
    64.                 if(!PhotonNetwork.IsMasterClient)
    65.                 {
    66.                     SyncMoveDir(moveDir);
    67.                 }
    68.  
    69.                 transform.Translate(moveDir * m_Speed * Time.deltaTime);
    70.  
    71.                 //limiting player move range
    72.                 if (transform.position.x <= minX)
    73.                 {
    74.                     transform.position = new Vector2(minX, transform.position.y);
    75.                 }
    76.  
    77.                 if (transform.position.x >= maxX)
    78.                 {
    79.                     transform.position = new Vector2(maxX, transform.position.y);
    80.                 }
    81.  
    82.                 if (transform.position.y <= minY)
    83.                 {
    84.                     transform.position = new Vector2(transform.position.x, minY);
    85.                 }
    86.  
    87.                 if (transform.position.y >= maxY)
    88.                 {
    89.                     transform.position = new Vector2(transform.position.x, maxY);
    90.                 }
    91.                 #endregion
    92.             }
    93.             #region player rotation
    94.             Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    95.             GFX.up = new Vector2(mousePos.x - transform.position.x, mousePos.y - transform.position.y);
    96.             #endregion
    97.         }
    98.         healthSlider.value = health;
    99.  
    100.         if(health <= 0)
    101.         {
    102.             gm.SetWinner("Player " + opponentNumber);
    103.         }
    104.     }
    105.  
    106.     [PunRPC]
    107.     private void RPCSyncMoveDir(Vector2 MoveDir)
    108.     {
    109.         moveDir = MoveDir;
    110.     }
    111.  
    112.     private void SyncMoveDir(Vector2 MoveDir)
    113.     {
    114.         pv.RPC("RPCSyncMoveDir", RpcTarget.All, MoveDir);
    115.     }
    116.  
    117.     public void TakeDamage(int damage)
    118.     {
    119.         pv.RPC("RPCTakeDamage", RpcTarget.All, damage);
    120.     }
    121.  
    122.     [PunRPC]
    123.     private void RPCTakeDamage(int damage)
    124.     {
    125.         health -= damage;
    126.     }
    127. }
    128.  
     
    Last edited: Dec 26, 2023