2

I have to spawn different objects and it's crucial that no two objects get repeated. What I mean is, random.range should not get two simultaneous numbers same, otherwise the code spawns same objects sometimes. Here's a simpler code to help you understand what I'm trying.

void Update () {

    j = Random.Range (1, 4); // this should give j values like=(1,2,1,3,2,1)
                              // and not this = (1,1,2,2...) the numbers should not repeat simultaneously.

    Inst();
}

void Inst(){

    if (j == 1) {

        //instantiate obj1
    }
    else if (j == 2) {

        instantiate obj2
    }

    else if (j == 3) {

        instantiate obj3
    }


}

Thank You!

Vivek Negi
  • 51
  • 1
  • 7
  • 4
    keep track of the previous value, don't let it generate that value on the next go – Jonesopolis Jan 02 '18 at 13:36
  • It's look like you are searching for [shuffle](https://stackoverflow.com/q/273313/4685428) – Aleks Andreev Jan 02 '18 at 13:38
  • How should I do that? Compare everytime using if? – Vivek Negi Jan 02 '18 at 13:38
  • Use Recursion. Every time a random number is generated, add it to a List. If theList.Contains() your random number, recurse your function until a new, unique, number is produced. – Brandon Miller Jan 02 '18 at 13:41
  • @BrandonMiller then he will never end up with a result like `1,2,1,3,2` (which is an acceptable outcome per his post) he doesn't want a result like this `1,1,2,3,1` – AresCaelum Jan 02 '18 at 13:43
  • Okay, then instead of adding your int to a list, just declare one int and set it every time the function is called. That way it will never be the same thing twice in a row, but will allow for repeated numbers later on. – Brandon Miller Jan 02 '18 at 13:46
  • 2
    Beware of using `while` loop in the accepted answer to do this. See duplicate for how to do this without a while loop. – Programmer Jan 02 '18 at 17:24

2 Answers2

5

How about

int lastValue;
public int UniqueRandomInt(int min, int max)
{
    int val = Random.Range(min, max);
    while(lastValue == val)
    {
        val = Random.Range(min, max);
    }
    lastValue = val;
    return val;
}

void Update() 
{
    UniqueRandomInt(1, 4);
    Inst();
}

void Inst()
{
    if (lastValue == 1)
    {
        //instantiate obj1
    }
    else if (lastValue == 2)
    {
        //instantiate obj2
    }
    else if (lastValue == 3)
    {
        //instantiate obj3
    }
}
Nikhil Agrawal
  • 47,018
  • 22
  • 121
  • 208
2

Your original statement picks 1 out of 3 possible numbers (1, 2, 3).

j = Random.Range(1, 4);

If you want to avoid the last issued number, then that leaves only 2 possible numbers.

Random.Range(1, 3)

Adding this random number to the previous value of j results in a new value that is equally random, but guaranteed to be different from the previous value of j.

j = j + Random.Range(1, 3);

Of course, you need to wrap values to keep them within the required range {1, 2, 3}:

if (j > 3) j -= 3;

Alternatively, use modulo (%) to make it a one-liner:

j = 1 + (j + Random.Range(0, 2)) % 3;

Works equally well for bigger ranges.

j = min + (j - min + Random.Range(1, max - min)) % (max - min);

This approach is more efficient than 'looping while duplicate'; there is no guaranteed limit to the number of iterations.

Ruud Helderman
  • 10,563
  • 1
  • 26
  • 45