# Problems with Random.Range

Hello, I’m using `Random.Range` to roll a 1d6 dice but it always seems to return the same number? Also (according to the Unity handbook) if the range is between two ints, and it rolls maximum, you will instead get the minimum. I think I’ve noticed this behaviour before, but it absolutely baffles me why this would be the case. Is there any way round it without converting from floats? Adding +1 to the maximum is not acceptable as that means there’s still a greater chance to roll a one than a six.

That doesn’t seem likely. When something used as often as random numbers doesn’t seem to work I would suggest that a developer check their code. Write a simple test that proves or disproves your theory.

The following says nothing about rolling the maximum. It is explaining that the max is “exclusive” i.e. that value is never returned. If you pass two identical integers then the min value is returned. What else could it do it only has one number in the range?

Note max is exclusive. Random.Range(0, 10) can return a value between 0 and 9. Return min if max equals min. The Random.Range distribution is uniform. Range is a Random Number Generator.

1 Like

I think this contradicts what you say. If the max is 10, the max it can actually return is 9. Therefore it never returns the maximum? This seems to be confirmed by the test, though I retract what I said about defaulting to one.

Yes the max value is never returned unless you use the same value for min and max.

(so Random.Range(1,1) will return 1).

In any case, what is the problem exactly?

Either use Random.Range(0,6) + 1, or Random.Range(1,7) to return the value for a six sided die.

Thanks. I’ve decided to do that. My issue is that I don’t think that’s how it should work and I have a whole host of `Random.Range` instances to do that for across about fifty files, and I’m not sure where they all are.

I mean, you can search within all your files. You could also make your own random range function that uses Random.Range and does the +1, so you can use values that make sense to you when you code.

Find them and remove them. Replace them with a proper API, something like:

``````int Roll1d6()
{
return Random.Range( 1, 7);
}
``````

A more-advanced API might do something like:

``````int EvaluateDice( string dice)
{
/// parse and roll the dice string
}
``````

where dice could be something complicated like `1d6` or `2d6+4` or `1d20+1d4` or whatever you happen to want.

There are libraries to do this already, but it’s so easy to write, I would just do it yourself. The benefits will begin to accumulate as soon as you start down this path.

Also, if in the future you ever need to debug your code with extremely rare dice rolls, just change that one function to return those numbers in order!

You should study a bit about languages in between Unity. The term “exclusive” means excluding so it is documented as being “less than” the maximum. Languages typically define the range as “exclusive” or “inclusive”. It works as designed.

1 Like

Seriously, you are not sure where they all are? Visual Studio will list them for you and you can jump to each one. And if read and understand AcidArrow’s response. You can wrap any library functionality in a function of your own. Add it to a static class and it is available anywhere. And if you find some other random library you prefer to use you change the implementation in that function and nowhere else.

Can we agree when you posted “it returns the same number” that it does not in fact return the same number?

I can tell you where most of them are, but there is always an outside chance I used it

It returned 5 about twenty times in a row. I don’t know why it started or stopped doing that. It could have been pure chance.

Ah yes, I had a heating system like that once.

Thanks. My current setup works around a similar system to the second one, but probably not as neat.

Random.Range reacts differently whether it is an int or a float so you need to check the doc each time to see if it is max inclusive or exclusive.

If you want some good algorithms there are CMWC and Mersenne Twister, the second one has some kind of copyright though.

I don’t see the point in a long discussion here. It’s simple, if you have d6 then the Range is 1 to 7 and the integer result is {1, 2, 3, 4, 5, 6}.

Range is not a dice simulator, it’s an RNG. So wrap it in a dice class and you’re done.

``````public class Dice
{
int sides = 6;

public int Roll()
{
return Random.Range(1, (sides + 1));
}
}
``````

In mathematical notation

• minInt <= randomInt < maxInt
• minF <= randomF <= maxF

It all depends on what system you have. In games, the range 0-5 (numbers on dice) is referred to as z6, and the range 1-6 (numbers on dice) as d6.

Edit:
Complementing the previous topic. Range probably requires this notation for integers, because the draw is done on a float anyway.

So how do you ensure an equal chance of rolling d6 on a float?

int 1 : {1.0f - 1.999999};
int 2 : {2.0f - 2.999999};
int 3 : {3.0f - 3.999999};
int 4 : {4.0f - 4.999999};
int 5 : {5.0f - 5.999999};
int 6 : {6.0f - 6.999999};
int 7 : {end of range}

If you add the +1 after the result your range is actually going to be 2-6.

When it comes to the int version of Range, the low end is inclusive. The high end is exclusive.
So, 0-6 returns 0,1,2,3,4,5. Thus adding 1 gives you 1,2,3,4,5,6.

1 Like

It is so odd that these types of discussions can continue for decades. If the random number generator that is included with Unity isn’t very random would someone generate data that shows the distribution is not normal? It would pretty much put an end to the discussion and would serve as evidence that could be shared with the Unity dev team.

1 Like

Well, Unity uses an xorshift variant for ages now (actually xorshift128) which is a quite cheap to compute but also quite good PRNG. That information had been shared by andeeeee a (former?) employee at Unity Technologies.

Depending on your exact usecase, if you want / need long term consistency, you may want to use your own implementation. I actually implemented an xorshift64 variant over here. So the internal state is only 64 bits, though for most applications that’s usually good enough.

Random generators have lots of uses but to get a random number when the user interacts you can as well take Time.deltaTime with some kind of modulo.

While this is true, this would not give you a good distribution and would change heavily depending on the users machine. Cryptographically secure random number generators usually “accumulate” entropy from various sources of the system (maybe audio hardware, mouse movement, CPU thread switching, RTC, using a PRNG to read / index RAM or files, …) over time. The difficult thing is usually how to properly map it to the desired range and still aim for a uniform distribution. A lot sources have a strong bias that is difficult to get rid of. So unless you studied those subjects indepth, I would not recommend to implement that yourself. You’re most likely make it worse ^^.