Search Unity

Third Party Mirror - Issues with syncing GameObject of connected players

Discussion in 'Multiplayer' started by Tomys_, Jun 8, 2019.

  1. Tomys_

    Tomys_

    Joined:
    Jun 7, 2019
    Posts:
    4
    Beginner question alert! I've been going through many tutorials, forums and solutions but still cannot understand how to correctly synchronize GameObject variables which holds a connected player object values.

    Here is the setup where I have:
    • I am using Mirror libraries which are basically the same as UNet;
    • GameController which has two variables: GameObject playerA and GameObject playerB. Both of these variables have [SyncVar] added.
    • PlayerPrefab which is spawnable object whenever player connects to server;
    • PlayerObject which is script for PlayerPrefab.
    Whenever player connects to the server, I order GameController to add this player's GameObject as either playerA or playerB (depending which one is free). Here is code:
    Code (CSharp):
    1. public class PlayerObject : NetworkBehaviour {
    2.     GameObject gamePrefab;
    3.     GameController gameController;
    4.  
    5.     void Start() {
    6.         gamePrefab = GameObject.FindGameObjectWithTag("GameController");
    7.         gameController = gamePrefab.GetComponent<GameController>();
    8.  
    9.         if (!isLocalPlayer) {
    10.             return;
    11.         }
    12.    
    13.         CmdAddPlayer(gameObject);
    14.         CmdUpdateRandomNumber(new System.Random().Next(0, 100));
    15.     }
    16.  
    17.     [Command]
    18.     void CmdAddPlayer(GameObject playerObject) {
    19.         if (gameController.xPlayer == null) {
    20.             gameController.xPlayer = playerObject;
    21.         } else if (gameController.oPlayer == null) {
    22.             gameController.oPlayer = playerObject;
    23.         }
    24.     }
    25.  
    26.     [Command]
    27.     void CmdUpdateRandomNumber(int newRandomNumber) {
    28.         gameController.randomNumber = newRandomNumber;
    29.     }
    30. }
    Code (CSharp):
    1. public class GameController : NetworkBehaviour {
    2.     [SyncVar] public int randomNumber;
    3.     [SyncVar] public GameObject xPlayer;
    4.     [SyncVar] public GameObject oPlayer;
    5. }

    I can see that on host the PlayerObject reference is updated for either playerA or playerB variable but it is not automatically synchronized with other clients.

    In Start() method you can see that I am trying to update simply random number as well exactly the same way. And the code is working properly and everything everywhere is synced but this is not working for the GameObject playerObject which is playerA and playerB. I can't understand why this is happening.
     
    Last edited: Jun 8, 2019
    zghc84 likes this.
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Naming a class PlayerObject and then an instance of a GameObject playerObject is confusing in your code.

    You don't need to send a reference to the GameObject in CmdAddPlayer, since that Command is called on the same GameObject on the host. You shouldn't even need to call that Command at all, just in Start check if it is the host, and if so run all that gameController code. Same thing with that CmdUpdateRandomNumber, unless you specifically want a random number generated on the client (not sure why the number needs to be from the client instead of just a new random number generated on the host).
     
  3. Tomys_

    Tomys_

    Joined:
    Jun 7, 2019
    Posts:
    4
    I've tried to understand your point and tried to do different ways of this but nothing is working. Could You maybe provide some pieces of code which would work properly? I just have absolutely no ideas anymore of what I need to update in my code in order to make this work.
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Well in your first Command, you're just sending the object a reference to itself. Not needed. The host knows when a new Player GameObject is spawned without the client telling it so in a Command, since the host is the one which spawned it in the first place.

    Something like this probably works:

    Code (CSharp):
    1. public class PlayerObject : NetworkBehaviour {
    2.     GameObject gamePrefab;
    3.     GameController gameController;
    4.  
    5.     void Start() {
    6.         gamePrefab = GameObject.FindGameObjectWithTag("GameController");
    7.         gameController = gamePrefab.GetComponent<GameController>();
    8.        
    9.         if (isServer)
    10.         {
    11.             addPlayer();
    12.             gameController.randomNumber = new System.Random().Next(0, 100);
    13.         }
    14.     }
    15.  
    16.     void addPlayer() {
    17.         if (gameController.xPlayer == null) {
    18.             gameController.xPlayer = gameObject;
    19.         } else if (gameController.oPlayer == null) {
    20.             gameController.oPlayer = gameObject;
    21.         }
    22.     }
    23.  
    24. }
     
  5. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    I haven't tried Mirror, and I stopped using Unet, so I don't know if there is any issue specifically with using syncvar references to networked GameObjects. If there is you could use some other identifier and fix things up on the client side instead of syncing the object reference itself.
     
  6. Tomys_

    Tomys_

    Joined:
    Jun 7, 2019
    Posts:
    4
    It looks that there are some issues with that because with Your solution GameObject values update only on host. They are not updated on clients. But the integer is updated on both - host and clients.
     
  7. Tomys_

    Tomys_

    Joined:
    Jun 7, 2019
    Posts:
    4
    I tried to use hooks in SyncVar for those two GameObject variables. Now those variables are synced on clients as well except for one exclusion: they are not synced on client connection. If I connect to the host where there are already some player inside, then I can see that xPlayer value is still null. If that player disconnects and connects back - in other words, forces some changes in those variables -, then I can see that xPlayer immediately syncs on client. Do You have any idea, what I should update in code so that client on connection retrieves the current values of GameObject variables from host?