,Hi, I need a little help regarding Random.Range returning duplicates.
In the below code I have two arrays:
public GameObject powerupPrefab;
public Transform powerupSpawnPoint;
The intention is that the length of my powerupSpawnPoint array is the maximum number of spawnpoints (This is working as intended)
However I do not want my gameobjects to spawn on top of one another, so although I need the return to be random it cannot be a duplicate as each index must be unique,
The problem is that Random Range will return duplicate indexes such as 0, 1, 1 and then only two of my potential three spawn points were used
here is the code in full
public class PowerupSpawner : NetworkBehaviour {
public GameObject[] powerupPrefab;
public Transform[] powerupSpawnPoint;
public override void OnStartServer()
{
for (int i = 0; i < powerupSpawnPoint.Length; i++)
{
int spawnIndex = Random.Range(0, powerupSpawnPoint.Length);
int prefabIndex = Random.Range(0, powerupPrefab.Length);
GameObject powerup = (GameObject)Instantiate(powerupPrefab[prefabIndex], powerupSpawnPoint[spawnIndex].position, powerupSpawnPoint[spawnIndex].rotation);
NetworkServer.Spawn(powerup);
}
}
}
I would use a List like this.
public class PowerupSpawner : NetworkBehaviour
{
public GameObject[] powerupPrefab;
public Transform[] powerupSpawnPoint;
public override void OnStartServer()
{
List<Transform> remainingSpawnPoints = new List<Transform>(powerupSpawnPoint);
for (int i = 0; i < powerupSpawnPoint.Length; i++)
{
int spawnPointIndex = Random.Range(0, remainingSpawnPoints.Count);
int prefabIndex = Random.Range(0, powerupPrefab.Length);
GameObject powerup = (GameObject)Instantiate(powerupPrefab[prefabIndex], remainingSpawnPoints[spawnPointIndex].position, remainingSpawnPoints[spawnPointIndex].rotation);
NetworkServer.Spawn(powerup);
remainingSpawnPoints.RemoveAt(spawnPointIndex);
}
}
}
I used to remember how to do that. It was basic C++ practice (sorting, shuffling, etc). There are always many ways to do it, and I’m sure someone will post a better method using some sort of built-in Unity function, but just to hold you over…
To the best of my memory, one time I needed a random enemy to spawn, but each enemy was unique and therefore I did not want two of the same enemy spawning, So I just used an array of the enemies, each holding the value of 1 or 0 (whether they had been spawned or not). Kind of like this:
//pseudo code (just example code, dynamic arrays are so nice...)
//Initialize
array Enemy[]; //make an array
int enemyNum = 3; //Game has 4 different enemies (0,1,2,3)
//Start
for (i = 0 to enemyNum) {Enemy[enemyNum] = 0;} //set all the enemies to 'not chosen'
eg, Enemy[0]=0;Enemy[1]=0;Enemy[2]=0; etc.
//Spawn function
When an enemy is randomly picked set it's corresponding array 'marker' to 1 (spawned already).
eg
// 1st, start a While loop (While 'none chosen')
// 2nd, pick a random number then check if corresponding enemy has already been spawned
While (Enemy[spawnedEnemy] = 0)
{
int spawnedEnemy = Random(range: 0 to enemyNum)
// int spawnedEnemy now equals 3 for example
if (Enemy[spawnedEnemy] = 0) // if Enemy[3] hasn't been spawned yet
{Enemy[spawnedEnemy] = 1;Spawn(Enemy[spawnedEnemy]);} //set the 'flag' and spawn the enemy object
} //end of While loop
Now whenever you call the custom Spawn() function you make, it should keep While-looping until it finds an enemy not spawned yet, then spawn that enemy and set it's Enemy[#] to 1
Hope that’s not confusing, I tried to explain the logic and not the code…