Prevent object from spawning at a spawn point twice in a row?

I have a set of spawn points and an object that I want to spawn from a random spawn point every second. I’ve used the InvokeRepeating function to make this work. But now, I want to modify the code a little bit. I don’t want the the object to be spawned from the same spawn point twice in a row.

Let’s say I have 5 spawn points: A, B, C, D, and E. When InvokeRepeating runs, the object is spawned randomly from spawn point C. So when InvokeRepeating runs again, I don’t want the object to spawn at spawn point C. It has to randomly pick another spawn point. I don’t want the object to spawn at at a particular spawn point twice in a row.

Here my code:

void Start () 
	{
		GameObject[] SP = GameObject.FindGameObjectsWithTag ("spawnPoint");
		spawnPoints = new Transform[SP.Length];
		for(int i=0; i < SP.Length; i++)
		{
			spawnPoints _= SP*.transform;*_

* }*

*InvokeRepeating(“SpawnObject”, spawnTime, spawnTime); *
* }*

void SpawnObject()
* {*
* int spawnPointIndex = Random.Range(0,spawnPoints.Length);*
* Instantiate(theObject, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);*
* }*
Any idea what I can add to my code so solve this?

If you are only concerned about the next and previous spawn points, then you can store the last spawn point index and find a new index that doesn’t match the previous one.

int prevSpawnIndex = -1;
void SpawnObject()
{
    int spawnPointIndex;

    do {
        spawnPointIndex = Random.Range(0,spawnPoints.Length);
    } while (prevSpawnIndex == spawnPointIndex && spawnPoints.Length > 1);
    prevSpawnIndex = spawnPointIndex;

    Instantiate(theObject, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
}

Something like this should work. It is a playlist approach, so each position is used exactly once, before it starts over again.

Note, that I haven’t tested this as I wrote it down here, outside of Visual Studio, so there can be some typos. :slight_smile:

private List<int> pendingSpawnPoints = new List<int>();

private void CreateSpawnList(int avoidedStartIndex) {
    List<int> tempList = new List<int>();
    for (int i=0; i<spawnPoints.Length; i++)
         tempList.Add(i);
    pendingSpawnPoints.Clear(); // it usually already is empty
    for (int i=0; i<spawnPoints.Length; i++) {
        int idx = Random.Range(0, tempList.Count);
        if (tempList[idx] == avoidedStartIndex)
            idx = (idx + 1) % tempList.Count;
        pendingSpawnPoints.Add(tempList[idx]);
        tempList.RemoveAt(idx);
    }
}

void Start () 
 {
     GameObject[] SP = GameObject.FindGameObjectsWithTag ("spawnPoint");
     spawnPoints = new Transform[SP.Length];
     for(int i=0; i < SP.Length; i++)
     {
         spawnPoints _= SP*.transform;*_

}
CreateSpawnList(-1);
InvokeRepeating(“SpawnObject”, spawnTime, spawnTime);
}

void SpawnObject() {
int spawnPointIndex = pendingSpawnPoints[0];
pendingSpawnPoints.RemoveAt(0);
if (pendingSpawnPoints.Count == 0)
CreateSpawnList(spawnPointIndex);
Instantiate(theObject, spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);
}

I have encountered the same issue before. I solved it by searching out an algorithm that generate unrepeated number.

Supposing u have five positions
Vector3[] genPoints = new Vector3[5];

You can get new positions by
int index = Random.Range(0, 5);

And you create another int array

int[] intArr = new int[5]; for(int i = 0; i < 5; ++i) intArr *= i*
Say index = 3 this time, then swap the value of intArr[3] and intArr[intArr.Count - 1] in intArr. Now you have 0, 1, 2, 4, 3 in intArray
And you got the generate point by genPoints[index];
The key point is next time you should Call index = Random.Range(0, 4) instead of Random.Range(0, 5), Now you only have “0, 1, 2, 4” these four values in intArr that can be accessed by intArr[index]
Then just reduce the random range by one for each time. Pretty simple algorithm but helpful