Search Unity

Unity.Mathematics.Random ALWAYS returning zero

Discussion in 'Entity Component System' started by JamesWjRose, Jan 3, 2020.

  1. JamesWjRose

    JamesWjRose

    Joined:
    Apr 13, 2017
    Posts:
    687
    So I have a job where I need to get one of a small collection or road/connection paths. There are between 2 and 8 possible connections. A small number, right. So I have the following code in Job's Execute:

    Code (CSharp):
    1.    
    2. Unity.Mathematics.Random mathRandom = new Unity.Mathematics.Random(randomSeed);
    3. int randomValue = mathRandom.NextInt(0, availableConnections.Length);
    4.  
    The "randomSeed" is created at each frame from the Time's millisecond, so this value is often different, though not ALWAYS (hey, there are only 1000 options to choose from)

    Anyway, the variable "randomValue" ALWAYS equals zero. If I change availableConnections.Length from 3 to 300, then I get different values. But when the value is 2, 3, or 4.... I only get zero chosen.

    Anyone have any thoughts?
     
  2. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    You can write a simple unit test that just use the Mathematics.Random (seed with 0~999 random number, then .nextint with 2 3 4) and then compare why in your code turns out different from the test.
     
  3. Singtaa

    Singtaa

    Joined:
    Dec 14, 2010
    Posts:
    492
    Code (CSharp):
    1. Unity.Mathematics.Random mathRandom = new Unity.Mathematics.Random(1337);
    2. for (int i = 0; i < 100; i++) {
    3.     Debug.Log(mathRandom.NextInt(0, 4));
    4. }
    Produces random ints between 0 and 3 (inclusive) for me.
     
    JamesWjRose likes this.
  4. 5argon

    5argon

    Joined:
    Jun 10, 2013
    Posts:
    1,555
    This test also pass, showing that I could get all values equally :

    Code (CSharp):
    1. [Test]
    2. public void RandomTest([NUnit.Framework.Range(2, 10)] int v)
    3. {
    4.     uint seed = (uint) (UnityEngine.Random.value * 10000);
    5.     Unity.Mathematics.Random mathRandom = new Unity.Mathematics.Random(seed);
    6.     int zeroCount = 0;
    7.     int nonZeroCount = 0;
    8.     for (int i = 0; i < 1000; i++)
    9.     {
    10.         int randomValue = mathRandom.NextInt(0, v);
    11.         if (randomValue == 0)
    12.         {
    13.             zeroCount++;
    14.         }
    15.         else
    16.         {
    17.             nonZeroCount++;
    18.         }
    19.     }
    20.  
    21.     float ratio = zeroCount / 1000f;
    22.     //Debug.Log($"{seed} {v} -> {zeroCount} {nonZeroCount} Ratio : {ratio}");
    23.     Assert.That(zeroCount, Is.GreaterThan(1));
    24.     Assert.That(nonZeroCount, Is.Not.Zero);
    25.     Assert.That(ratio, Is.EqualTo(1f / v).Within(0.05f), "Random is uniformly distributed.");
    26. }
    27.  
     
    JamesWjRose likes this.
  5. JamesWjRose

    JamesWjRose

    Joined:
    Apr 13, 2017
    Posts:
    687
    I SEEM to have found the issue. Because I was using the current time's millisecond, I only got seed values between 0 and 1000. When I use System.Random to create a seed that is between 0 and 100,000 I then get random values for the range I want. Seems odd, but then my understanding of Unity's Random design or abilities.
     
    Krooq and JonasMumm like this.
  6. Rud156

    Rud156

    Joined:
    Dec 25, 2017
    Posts:
    3
    I too faced the same problem. Not really sure why the seed range will affect the output of values. Can anyone give some explanation? I'm surely missing something.
     
  7. Drezta

    Drezta

    Joined:
    Nov 4, 2012
    Posts:
    8
    As far as I understand random number generation follows a (complex) pattern, the bigger the seed range the more entropy the pattern has to work with.
     
    JamesWjRose likes this.
  8. JamesWjRose

    JamesWjRose

    Joined:
    Apr 13, 2017
    Posts:
    687
    Ok, thank you kindly for the details.
     
    tarkhon likes this.
  9. Guedez

    Guedez

    Joined:
    Jun 1, 2012
    Posts:
    827
    I once had the same issue, it was because some other code that I wrote 15 months ago was writing the seed to 0 every frame to ensure it's own deterministicality and it would never set the seed value back to what it was before it ran, thus anything that ran after it, would also be deterministic. In case someone run into the same issue but it was not what OP's detected as his own issue
     
    JamesWjRose likes this.
  10. DevViktoria

    DevViktoria

    Joined:
    Apr 6, 2021
    Posts:
    94
    I have a similar problem. If I call NextInt after I had generated a new Random I constantly getting 0-s for the first time. I should call NextInt for the second time to get a non zero value. Here is the code that it is an OnUpdate of a system:
    Code (CSharp):
    1. uint seed = System.Convert.ToUInt32(Time.ElapsedTime * 10);
    2. seed = seed == 0 ? 1 : seed;
    3. Random random = new Random(seed);
    4. int index = random.NextInt(7);
    5. int index2 = random.NextInt(7);
    6.  
    7. UnityEngine.Debug.Log($"Seed: {seed}; index: {index}; index2: {index2}");
    index is constantly zero, index2 is not constantly zero.
     
  11. Krooq

    Krooq

    Joined:
    Jan 30, 2013
    Posts:
    196
    This sounds like the ol' autocast of float to int issue. Gets me every time.
     
    DevViktoria likes this.
  12. tarkhon

    tarkhon

    Joined:
    Jan 31, 2020
    Posts:
    1
    I had the same issue. I was using Entity.Index as seeds and the result was always near zero on the first random number. Using Random.CreateFromIndex fixed the problem for me.
    Code (CSharp):
    1. Random rand = new Random(seed);
    2. rand.NextFloat(); // result is near zero
    3.  
    4. Random rand = Random.CreateFromIndex(seed);
    5. rand.NextFloat(); // result is random
     
    bb8_1, bartofzo and apkdev like this.
  13. bartofzo

    bartofzo

    Joined:
    Mar 16, 2017
    Posts:
    151
    Same thing... needed a determinstic random and initializing the Random and calling NextInt(0,2) gives the same intiial result for seeds that are close to each other. I would have expected a different seed giving totally different results but it doesn't. Unity should document this better!
     
  14. tertle

    tertle

    Joined:
    Jan 25, 2011
    Posts:
    3,761
    I ran some numbers on discord for this the other week because people weren't aware of the sequential seed issue.

    If you just call Random.NextInt(10) then
    seeds 1-1600 all return 0
    seeds 1601-1616 all return 1
    skipping ahead
    seeds 10001-10010 all return 5
    etc

    Always hash sequential seeds (via CreateFromIndex)
     
    Last edited: Apr 5, 2024
    bartofzo, bb8_1 and jivalenzuela like this.