Search Unity

How to Sync variables in Unity3D Networking

Discussion in 'Multiplayer' started by ibgk883, Feb 10, 2019.

  1. ibgk883

    ibgk883

    Joined:
    Jan 29, 2019
    Posts:
    3
    Hello Title was too general but I have several problems in my mind. I am new at UnityNetworking. I am watching youtube tutorial from quill18 and trying to implement on my project. So I know [SyncVar] values can only set and sync in server. But even I check isServer > hasAuthority > isLocalPlayer I cant be able to sync them properly. I can only be able to sync them only and only under isServer. Here is problem begins..

    • So I have two public int variables with [SyncVar] and I am checking their values from Unity3D if they changed.

    • If I change them under isServer if statement, they are changing both in Server and Client to 100 and 100.

    • But after this If I change them in hasAuthority if statement they wont change same goes for isLocalPlayer...

    • I tried changing them in a function before checking if isServer doesnt work.

    • Even I try [Command] function, I know it runs in Server values still didn't change.
    Code (CSharp):
    1. private void Update()
    2. {
    3.     ServerUpdate();
    4.     ClientUpdate();
    5. }
    6.  
    7. [SyncVar] public int syncIT_1;
    8. [SyncVar] public int syncIT_2;
    9.  
    10. void WillItSyncNow()
    11. {
    12.     if (isServer)
    13.     {
    14.         syncIT_1 = 300;
    15.         syncIT_2 = 300;
    16.     }      
    17. }
    18.  
    19. [Command]
    20. void CmdSyncPlease()
    21. {
    22.     syncIT_1 = 400;
    23.     syncIT_2 = 400;
    24. }
    25.  
    26. void ServerUpdate()
    27. {      
    28.      if (isServer)  
    29.     {      
    30.         syncIT_1 = 100;
    31.         syncIT_2 = 100;
    32.  
    33.         if (hasAuthority)
    34.         {
    35.             syncIT_1 = 200;
    36.             syncIT_2 = 200;
    37.  
    38.             if (isLocalPlayer == true)
    39.             {
    40.             WillItSyncNow();
    41.             CmdSyncPlease();
    42.             }
    43.         }
    44.     }
    45. }
    https://prnt.sc/mja8nz > Server Client Values
    https://prnt.sc/mja978 > Client Values
     
  2. mischa2k

    mischa2k

    Joined:
    Sep 4, 2015
    Posts:
    4,347
    You should probably post the full script and not only a part of it
     
  3. ibgk883

    ibgk883

    Joined:
    Jan 29, 2019
    Posts:
    3
    Code (CSharp):
    1.  
    2. #pragma warning disable CS0618
    3. using System.Collections;
    4. using UnityEngine;
    5. using UnityEngine.Networking;
    6. using UnityEngine.UI;
    7. public class GameManager : NetworkBehaviour
    8. {
    9.     //VARIABLES
    10.     const int TURN_TIME = 5;
    11.     public static QuestionList QuestionList = new QuestionList();
    12.     [SyncVar] public int rndmQuestionNumber;
    13.     [SyncVar] public int rndmOptionNumber;
    14.     [SyncVar] public int sync_IT1;
    15.     [SyncVar] public int sync_IT2;
    16.     Button NextQuestionButton;
    17.     GameObject NextQuestionButtonGO;
    18.     GameObject IpCanvas;
    19.     GameObject Timer;
    20.     GameObject QuestionText;
    21.     Button Option_1;
    22.     Button Option_2;
    23.     Button Option_3;
    24.     Button Option_4;
    25.     public bool DidIAnswer = false;
    26.     public bool CanvasShow = false;
    27.     public bool ButtonShow = false;
    28.     public bool RunOnce = true;
    29.     public string checkText = "";
    30.     public float TurnTimer;
    31.     // FUNCTIONS
    32.     private void Start()
    33.     {
    34.         IpCanvas = GameObject.Find("IPCanvas");
    35.         Timer = GameObject.Find("Timer");
    36.         NextQuestionButton = IpCanvas.GetComponentInChildren<Button>();
    37.         NextQuestionButton.onClick.AddListener(startNextTurn);
    38.         NextQuestionButtonGO = GameObject.Find("NextButton");
    39.         QuestionText = GameObject.Find("Question");
    40.         Option_1 = GameObject.Find("Option_1").GetComponent<Button>();
    41.         Option_2 = GameObject.Find("Option_2").GetComponent<Button>();
    42.         Option_3 = GameObject.Find("Option_3").GetComponent<Button>();
    43.         Option_4 = GameObject.Find("Option_4").GetComponent<Button>();
    44.         Option_1.onClick.AddListener(option1Clicked);
    45.         Option_2.onClick.AddListener(option2Clicked);
    46.         Option_3.onClick.AddListener(option3Clicked);
    47.         Option_4.onClick.AddListener(option4Clicked);
    48.         CanvasEnabled(false);
    49.         ButtonEnabled(false);
    50.         getQuestionList();
    51.     }
    52.     private void CanvasEnabled(bool ISIT)
    53.     {
    54.         // Bu Arayüz Canvasının kontrol(show/hide) fonksiyonu!
    55.         if (ISIT)
    56.         {
    57.             IpCanvas.GetComponent<Canvas>().enabled = ISIT;
    58.         }
    59.         else
    60.         {
    61.             IpCanvas.GetComponent<Canvas>().enabled = ISIT;
    62.         }
    63.         CanvasShow = ISIT;
    64.     }
    65.     private void ButtonEnabled(bool ISIT)
    66.     {
    67.         // Bu Arayüz Canvasındaki BUTTONun kontrol(show/hide) fonksiyonu!
    68.         if (ISIT)
    69.         {
    70.             NextQuestionButtonGO.GetComponent<Canvas>().enabled = ISIT;
    71.         }
    72.         else
    73.         {
    74.             NextQuestionButtonGO.GetComponent<Canvas>().enabled = ISIT;
    75.         }
    76.         ButtonShow = ISIT;
    77.     }
    78.     private void getQuestionList()
    79.     {
    80.         CanvasEnabled(false);
    81.         ButtonEnabled(false);
    82.         //JSON Datayı ceken fonksiyon
    83.         TextAsset asset = Resources.Load("history") as TextAsset;
    84.         if (asset != null)
    85.         {
    86.             QuestionList = JsonUtility.FromJson<QuestionList>(asset.text);
    87.         }
    88.         else
    89.         {
    90.             Debug.Log("Assets are null!");
    91.         }
    92.     }
    93.     private void Update()
    94.     {
    95.         ServerUpdate();
    96.         //ClientUpdate();
    97.     }
    98.     // TODO: SYNCVAR SADECE ISSERVER ALTINDA CALISIYOR BUNU DÜZELTMEN GEREK
    99.     // TODO: rndmQuestionNumber & rndmOptionNumber somehow dont sync fix it. !!!
    100.     void ServerUpdate()
    101.     {
    102.         // Bu fonksiyon sadece Serverda calısır. Server aynı zamanda Clientsa'da calısır.
    103.         if (isServer)
    104.         {
    105.             sync_IT1 = rndmQuestionNumber;
    106.             sync_IT2 = rndmOptionNumber;
    107.             if (isLocalPlayer)
    108.             {
    109.                 TurnTimer -= Time.deltaTime;
    110.                 RpcTurnTimerRemaining(TurnTimer);
    111.                 if (RunOnce)
    112.                 {                  
    113.                     startTheGame();
    114.                 }
    115.                 if (TurnTimer <= 0)
    116.                 {
    117.                     TurnTimer = 0;
    118.                     Debug.Log("TUR BİTTİ");
    119.                     RpcCheckAnswer("");
    120.                 }
    121.                 if (CanvasShow)
    122.                 {
    123.                     //TODO: Diger oyuncuların cevaplarını kontrol et eger hepsi cevaplamıssa timer baslat
    124.                     if (DidIAnswer)
    125.                     {
    126.                         ButtonEnabled(true);
    127.                     }
    128.                 }
    129.             }
    130.         }
    131.     }
    132.     void ClientUpdate()
    133.     {
    134.         //Bu fonksiyon sadece ve sadece Clientlarda calısır, Eğer Client ve Server ise calısmaz..
    135.         if (isServer == false)
    136.         {
    137.             if (hasAuthority)
    138.             {
    139.                 if (isLocalPlayer == true)
    140.                 {
    141.                     if (TurnTimer <= 0)
    142.                     {
    143.                         TurnTimer = 0;
    144.                         checkAnswer("");
    145.                     }
    146.                 }
    147.             }
    148.         }
    149.     }
    150.     IEnumerator RpcSetQuestionIE()
    151.     {
    152.         yield return new WaitForSeconds(0.5f);
    153.         RpcSetQuestion(rndmQuestionNumber, rndmOptionNumber);
    154.     }
    155.     [ClientRpc]
    156.     void RpcTurnTimerRemaining(float turntimer)
    157.     {
    158.         Timer.GetComponent<Text>().text = turntimer.ToString("0");
    159.     }
    160.     //[ClientRpc] void RpcDEGERUPDATE(int a, int b)
    161.     //{
    162.     //    rndmQuestionNumber = a;
    163.     //    rndmOptionNumber = b;
    164.     //}
    165.     [ClientRpc]
    166.     void RpcSetQuestion(int question, int option)
    167.     {
    168.         Debug.Log("SERVER TARAFINDAN GÖNDERİLEN " + question + " " + option + " " + "İLE SORUMU OLUŞTURDUM");
    169.         Debug.Log("TURN TIMERDAN GELEN DEGER İLE SÜREYİ AYARLADIM: " + TurnTimer);
    170.         DidIAnswer = false;
    171.         CanvasEnabled(false);
    172.         ButtonEnabled(false);
    173.         QuestionText.GetComponentInChildren<Text>().text = QuestionList.Question[question].question;
    174.         GameObject.Find("Option_" + option).GetComponentInChildren<Text>().text = QuestionList.Question[question].answer.ToString();
    175.         generateOtherOptions(question, option);
    176.     }
    177.     void generateOtherOptions(int question, int option)
    178.     {
    179.         // Bu fonksiyon secilen sorunun cevabını alıp eger cevap belli aralıklardan büyükse
    180.         // ona göre MİN MAX olusturup generateOptionsTexts ine MİN MAX değerlerini gönderiyor
    181.         int min = 0;
    182.         int max = 0;
    183.         if (QuestionList.Question[question].answer > 2000)
    184.         {
    185.             max = 400;
    186.             generateOptionsTexts(min, max, question, option);
    187.         }
    188.         else if (QuestionList.Question[question].answer > 1000)
    189.         {
    190.             max = 100;
    191.             generateOptionsTexts(min, max, question, option);
    192.         }
    193.         else if (QuestionList.Question[question].answer > 500)
    194.         {
    195.             max = 500;
    196.             generateOptionsTexts(min, max, question, option);
    197.         }
    198.         else if (QuestionList.Question[question].answer > 100)
    199.         {
    200.             max = 100;
    201.             generateOptionsTexts(min, max, question, option);
    202.         }
    203.         else if (QuestionList.Question[question].answer > 10)
    204.         {
    205.             max = 10;
    206.             generateOptionsTexts(min, max, question, option);
    207.         }
    208.         else
    209.         {
    210.             max = 3;
    211.             generateOptionsTexts(min, max, question, option);
    212.         }
    213.     }
    214.     void generateOptionsTexts(int min, int max, int question, int option)
    215.     {
    216.         // Bu fonksiyon her bir şık için almış olduğu MİN MAX değerlerini
    217.         // o şıkkın Texti oluşturulması için generateText fonksiyonuna gönderiyor.
    218.         for (int i = 1; i <= 4; i++)
    219.         {
    220.             if (option == i)
    221.             {
    222.                 generateText(i, min, max, question);
    223.             }
    224.         }
    225.     }
    226.     void generateText(int index, int min, int max, int question)
    227.     {
    228.         // Bu fonksiyon dışarıdan gelen doğru cevap şıkkı MİN ve MAX değerini işleyip olusturduğu random sayının
    229.         // 2ye bölümüne göre çıkartıyor, topluyor ve doğru cevap ise hic ellemiyor bu şekilde 4 şık olusturuyor.
    230.         int rndmEven = Random.Range(1, 10);
    231.         for (int i = 1; i <= 4; i++)
    232.         {
    233.             int rndm = Random.Range(min, max);
    234.             if (rndmEven % 2 == 0)
    235.             {
    236.                 if (i == index)
    237.                 {
    238.                     continue;
    239.                 }
    240.                 else
    241.                 {
    242.                     GameObject.Find("Option_" + i).GetComponentInChildren<Text>().text = (QuestionList.Question[question].answer + rndm).ToString();
    243.                 }
    244.             }
    245.             else
    246.             {
    247.                 if (i == index)
    248.                 {
    249.                     continue;
    250.                 }
    251.                 else
    252.                 {
    253.                     GameObject.Find("Option_" + i).GetComponentInChildren<Text>().text = (QuestionList.Question[question].answer - rndm).ToString();
    254.                 }
    255.             }
    256.         }
    257.     }
    258.     void startTheGame()
    259.     {
    260.         TurnTimer = TURN_TIME;
    261.         rndmQuestionNumber = Random.Range(0, QuestionList.Question.Count + 1);
    262.         rndmOptionNumber = Random.Range(1, 5);
    263.         StartCoroutine(RpcSetQuestionIE());
    264.         RunOnce = false;
    265.     }
    266.     void startNextTurn()
    267.     {
    268.         // Only if Host clicks Button
    269.         ButtonEnabled(false);
    270.         RunOnce = true;
    271.         TurnTimer = TURN_TIME;
    272.     }
    273.     public void option1Clicked()
    274.     {
    275.         if (isLocalPlayer)
    276.         {
    277.             checkText = Option_1.GetComponentInChildren<Text>().text;
    278.             checkAnswer(checkText);
    279.         }
    280.     }
    281.     public void option2Clicked()
    282.     {
    283.         if (isLocalPlayer)
    284.         {
    285.             checkText = Option_2.GetComponentInChildren<Text>().text;
    286.             checkAnswer(checkText);
    287.         }
    288.     }
    289.     public void option3Clicked()
    290.     {
    291.         if (isLocalPlayer)
    292.         {
    293.             checkText = Option_3.GetComponentInChildren<Text>().text;
    294.             checkAnswer(checkText);
    295.         }
    296.     }
    297.     public void option4Clicked()
    298.     {
    299.         if (isLocalPlayer)
    300.         {
    301.             checkText = Option_4.GetComponentInChildren<Text>().text;
    302.             checkAnswer(checkText);
    303.         }
    304.     }
    305.     [ClientRpc]
    306.     void RpcCheckAnswer(string text)
    307.     {
    308.         DidIAnswer = true;
    309.         string answer = text;
    310.         CanvasEnabled(true);
    311.         ButtonEnabled(true);
    312.         if (QuestionList.Question[rndmQuestionNumber].answer.ToString() == answer)
    313.         {
    314.             IpCanvas.GetComponentInChildren<Text>().text = "Doğru Cevap";
    315.             Debug.Log("Doğru Cevap");
    316.         }
    317.         else
    318.         {
    319.             IpCanvas.GetComponentInChildren<Text>().text = "Yanlış Cevap";
    320.             Debug.Log("Yanlış Cevap: " + text + " , " + " Doğru Cevap: " + QuestionList.Question[rndmQuestionNumber].answer.ToString());
    321.         }
    322.     }
    323.     void checkAnswer(string text)
    324.     {
    325.         DidIAnswer = true;
    326.         string answer = text;
    327.         CanvasEnabled(true);
    328.         ButtonEnabled(true);
    329.         if (QuestionList.Question[rndmQuestionNumber].answer.ToString() == answer)
    330.         {
    331.             IpCanvas.GetComponentInChildren<Text>().text = "Doğru Cevap";
    332.             Debug.Log("Doğru Cevap");
    333.         }
    334.         else
    335.         {
    336.             IpCanvas.GetComponentInChildren<Text>().text = "Yanlış Cevap";
    337.             Debug.Log("Yanlış Cevap: " + text + " , " + " Doğru Cevap: " + QuestionList.Question[rndmQuestionNumber].answer.ToString());
    338.         }
    339.     }
    340. }
    341.  
    In general I have only issue here with when I want to Syncvar my rndmQuestionNumber and rndmOptionNumber both server and clients I cant
     
  4. ibgk883

    ibgk883

    Joined:
    Jan 29, 2019
    Posts:
    3
    The main problem here: I can Sync Values under first isServer control from ServerUpdate like syncIT_1 = 100; and then both clients and server got value of 100. But when I do like syncIT_1 = Random.Range(1, 100); both client and server get different values which I really want to know why. Isn't suppose to sync values from server side?.
     
  5. Cranom

    Cranom

    Joined:
    Jan 31, 2018
    Posts:
    26
    You might want to take a look at this topic about SyncVar:
    https://forum.unity.com/threads/unity-networking-notes.596602/


    Looking at your first post, the host (who is server AND client with local authority at the same time) is setting the syncvar at 400 in the first pass the moment the server is up and no one's there.
    Then because it is already at 400, infinitly setting it at 400 won't do anything because it updates towards the clients only on change. And since the initialization occured before any clients joined and SyncVar do not update toward late comming clients, it stays at 100 for them since it's probably what they were set at in the public field.

    Try updating the syncvar after every clients you want are connected to the server and just do:

    Code (CSharp):
    1. if (isServer & Input.GetKeyDown (KeyCode.A))
    2.     syncIT_1 += 1;
    3. else if (hasAuthority & Input.GetKeyDown (KeyCode.A))
    4.     CmdSyncPlease();