- Home /
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[i] = SP[i].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?
Answer by Jessespike · Jul 28, 2016 at 06:30 PM
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);
}
I totally forgot about this. Sorry for taking so long.
Answer by ScaniX · Jul 28, 2016 at 06:42 PM
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. :)
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[i] = SP[i].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);
}
Answer by milanow · Jul 29, 2016 at 12:31 PM
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] = 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