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

Random number sync between server and client

Discussion in 'Multiplayer' started by jdcart, Feb 2, 2017.

  1. jdcart

    jdcart

    Joined:
    Jun 24, 2015
    Posts:
    15
    Hello,

    I'm learning how to use UNet and at the moment I'm just trying to build some simple samples that will help in the long run on the development of my application. Right now, I have a simple scene with 2 players and a text field where I feed random numbers that updates every 2 seconds. The problem that I have is that the numbers are always different between client/server or server/client/client. My final application will have a server/client architecture, meaning none of the clients are going to be hosts.

    I want the server to send the messages to each of the clients. In my current setup I have a script on my text prefab that changes the random number, the text prefab is also registered as a spawnable prefab in the network manager and it has a network identity component which doesn't have the "Server" or "Local Player Authority" checkboxes on. I also have a empty object with a script and a network identity component with the "Server" flag on, that takes care of spawning the text prefab.

    Code (CSharp):
    1. //This is the code that spawns the text prefab object
    2.  
    3.     [SerializeField]
    4.     private GameObject counterPrefab;
    5.  
    6.     public override void OnStartServer()
    7.     {
    8.         //Create prefab instance
    9.         GameObject counter = (GameObject)Instantiate(counterPrefab, transform.position, Quaternion.identity);
    10.         //Spawn
    11.         NetworkServer.Spawn(counter);
    12.     }
    Given my setup I was expecting that using SyncVars would send the messages from the server and update correctly on each of the clients, but that wasn't the case. I tried an Rcp call but it didn't work either, I know that I'm doing something wrong. I'm hoping someone can guide me in the right direction.

    Code (CSharp):
    1.     //This is the code that is running on the text prefab
    2.     //to change the numbers and sync
    3.  
    4.     [SerializeField]
    5.     private Text counter;
    6.  
    7.     private string numbers;
    8.     [SyncVar]
    9.     private float randomNumber;
    10.     private float timer = 0;
    11.  
    12.     void Update()
    13.     {
    14.         RpcCounter();
    15.     }
    16.    
    17.     //I had an Rpc here but I removed it because it didn't work
    18.     void RpcCounter()
    19.     {
    20.         //Start counting
    21.         timer += Time.deltaTime;
    22.  
    23.         if (timer >= 2)
    24.         {
    25.             randomNumber = Random.Range(1, 10);
    26.             numbers = randomNumber.ToString();
    27.             counter.text = numbers;
    28.             Debug.Log("Selected number:" + " " + numbers);
    29.             //genRandomNum(numbers);
    30.             timer = 0;
    31.         }
    32.     }
    Thanks in advance!
     
  2. Jos-Yule

    Jos-Yule

    Joined:
    Sep 17, 2012
    Posts:
    292
    Sketch of how you could try it.

    Code (CSharp):
    1. // Assuming your text prefab is a networkBehaviour
    2.  
    3. [SyncVar(hook="RandomNumberSyncCallback")]
    4. float randomNumber;
    5.  
    6. void Update()
    7. {  
    8.     // Note - you will have to change the updates per frame for whatever channel you are using
    9.     // on this object if you want to push a new value every frame.
    10.     if(isServer)
    11.     {  
    12.         randomNumber = CreateYourRandomNumberHere();
    13.     }
    14. }
    15.  
    16.  
    17. void RandomNumberSyncCallback(float newNumber)
    18. {
    19.     if(isServer) return;
    20.     Debug.Log("I'm a client, got a new number!", this);
    21.     randomNumber = newNumber;
    22. }
    23.  
     
    jdcart likes this.
  3. jdcart

    jdcart

    Joined:
    Jun 24, 2015
    Posts:
    15
    That worked perfectly, thanks for the help! I'll leave the code that I'm using if anyone is doing something similar.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using UnityEngine.Networking;
    4.  
    5. [NetworkSettings(channel = 0, sendInterval = 0)]
    6. public class Counter : NetworkBehaviour
    7. {
    8.     [SerializeField]
    9.     private Text counter;
    10.  
    11.     private float timer = 0;
    12.  
    13.     [SyncVar(hook = "RandomNumberSyncCallback")]
    14.     string randomNumber;
    15.  
    16.     void RandomNumberSyncCallback(string newNumber)
    17.     {
    18.         if (isServer) return;
    19.  
    20.         randomNumber = newNumber;
    21.         counter.text = randomNumber;
    22.         Debug.Log(randomNumber);
    23.     }
    24.  
    25.     void Update()
    26.     {
    27.         if (isServer)
    28.         {
    29.             timer += Time.deltaTime;
    30.  
    31.             if (timer >= 2)
    32.             {
    33.                 randomNumber = Random.Range(1, 10).ToString();
    34.                 counter.text = randomNumber;
    35.                 timer = 0;
    36.             }
    37.         }
    38.     }
    39. }
    40.  
     
  4. awund1

    awund1

    Joined:
    Sep 6, 2017
    Posts:
    7
    Awesome! thank you :)
     
  5. FuzzyQuills

    FuzzyQuills

    Joined:
    Jun 8, 2013
    Posts:
    2,871
    If you're still working on this, you could try generating a seed from the system clock, then sending that instead.
    With what you've got though, that works well. For certain "random number" things however, it may be worth generating your own seed, then setting the Random seed manually. (Then, of course, updating clients with the seed)

    Source: My game project Plasma Fauna has an unused random seed store for when I implement networked play at a later stage, since that game uses procedural generation based on random numbers.
     
  6. Jos-Yule

    Jos-Yule

    Joined:
    Sep 17, 2012
    Posts:
    292
    Do note that different cpu architectures may not return the same values for the same seed. If you really need this then you have to be sure you are using a deterministic RNG which is deterministic across all cpus.