Unity.Mathematics.Random ALWAYS returning zero

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:

Unity.Mathematics.Random mathRandom = new Unity.Mathematics.Random(randomSeed);
int randomValue = mathRandom.NextInt(0, availableConnections.Length);

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?

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.

Unity.Mathematics.Random mathRandom = new Unity.Mathematics.Random(1337);
for (int i = 0; i < 100; i++) {
    Debug.Log(mathRandom.NextInt(0, 4));
}

Produces random ints between 0 and 3 (inclusive) for me.

1 Like

This test also pass, showing that I could get all values equally :

[Test]
public void RandomTest([NUnit.Framework.Range(2, 10)] int v)
{
    uint seed = (uint) (UnityEngine.Random.value * 10000);
    Unity.Mathematics.Random mathRandom = new Unity.Mathematics.Random(seed);
    int zeroCount = 0;
    int nonZeroCount = 0;
    for (int i = 0; i < 1000; i++)
    {
        int randomValue = mathRandom.NextInt(0, v);
        if (randomValue == 0)
        {
            zeroCount++;
        }
        else
        {
            nonZeroCount++;
        }
    }

    float ratio = zeroCount / 1000f;
    //Debug.Log($"{seed} {v} -> {zeroCount} {nonZeroCount} Ratio : {ratio}");
    Assert.That(zeroCount, Is.GreaterThan(1));
    Assert.That(nonZeroCount, Is.Not.Zero);
    Assert.That(ratio, Is.EqualTo(1f / v).Within(0.05f), "Random is uniformly distributed.");
}
1 Like

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.

2 Likes

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.

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.

1 Like

Ok, thank you kindly for the details.

1 Like

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

1 Like

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:

uint seed = System.Convert.ToUInt32(Time.ElapsedTime * 10);
seed = seed == 0 ? 1 : seed;
Random random = new Random(seed);
int index = random.NextInt(7);
int index2 = random.NextInt(7);

UnityEngine.Debug.Log($"Seed: {seed}; index: {index}; index2: {index2}");

index is constantly zero, index2 is not constantly zero.

1 Like

This sounds like the ol’ autocast of float to int issue. Gets me every time.

1 Like

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.

Random rand = new Random(seed);
rand.NextFloat(); // result is near zero

Random rand = Random.CreateFromIndex(seed);
rand.NextFloat(); // result is random
4 Likes

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!

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)

3 Likes