# Best way to spawn random amount of enemies and in different spots??

So I have a 2x20 grid of possible spawn points, all in an array. What I want is to have an int called spawnChance, as well as a wave value. Then, I can take the wave value, and select [wave] amount of points out of the 40 possible points. Then each of those points has a 1 in [spawnChance] chance of spawning an enemy. This means that the amount of enemies is directly correlated to the wave as well as spawn chance, while still having some variation, which as means I can make waves completely procedural once I get to that point. So, what I tried to do is:

``````void SpawnWave(int wave){
foreach(GameObject spawn in spawnLocations){
int spawnOutcome = Random.Range(0, wave + 1);
if(spawnOutcome >= spawnChance / 2){
Vector3 enemySpawnPos = new Vector3(spawn.transform.position.x, spawn.transform.position.y + 1.5f, spawn.transform.position.z);
Object.Instantiate(enemy1, enemySpawnPos, Quaternion.Euler(0, -90, 0), enemyHolder.transform);
}
}
}
``````

but this is completely unreliable, and the amount of enemies has no correlation to spawnChance or the wave number, unless the wave number is 1 in which case nothing spawns. Now I’m in a brain fart state, and can’t think of how I could work this out. I know how to get the spawnChance number, I just can’t figure out how I’m going to select random points on the grid efficiently, since starting at 0 with a random number between 0 and wave means I’m more likely to get enemies in the beginning of the array than the end. How could I work this out to be a good wave spawner, where the amount of enemies is correlated to the wave number and spawn chance while still being random in the amount of enemies spawn and where?

don’t you find interesting that instead of presenting a raw problem, you’ve basically presented your own non-working solution to it. and so we have to work backward to be able to understand what you really want to achieve based on what you thought would help you achieve that. it’s a bit tiresome.

if you have a general 2D area with discrete units (aka tiles), and you want to introduce a chance to spawn, you need to consider that such a constraint is very loose and you won’t have any guarantees for the distribution or the actual amount of the enemies spawned.

that said,

a) you can simply run through each tile and test `random < chance`. (alternatively, you can run though tiles at random, and spawn on vacant spots until you deplete some counter.)

b) if you want to constrain a fixed amount of enemies to spawn, then you have to consider the distribution, otherwise nothing stops the randomization from clumping them all in one spot. or this might be something that you want. or you really need the enemies to be spread some distance apart. in the latter case you can solve this by implementing a Poisson disc sampler.

c) if you want your individual tiles to be of varying likelihoods, you could randomly assign the chances themselves, which would be an interesting high-level practice. in that case you might want to consider making a weighted choice, where you populate a list, but treat this list if it were a visual thing and not just an abstract data structure. namely, if things have varying heights in a list, and you sort them by this height, comparing some random absolute height will let you choose some item, and so you get a behavior of a natural weighted choice. natural in a sense that this is quite similar to how bigger surfaces in a game of darts have proportionally greater probability of being hit, simply by nature alone. the trick with the weighted list is to find a way to quickly pick the winner in a deterministic fashion. there is no known algorithm for this, but the whole thing is very easy to conceptualize if you need it.

d) when working with a fixed amount of enemies, you can also employ a dirty trick of try-and-repeat. you can, for example, use a perlin noise to arbitrarily distribute your odds over an area, then treat it as a threshold (basically `perlin < threshold`), and keep repeating this process with varying perlin offsets until you’ve hit the final spawn. a condition to fail would be for example, picking a tile that is already populated, or picking a tile that is too close too a populated one. rinse and repeat.

e) a hybrid between (d) and (b) would be to treat the area as a heat map, where things get hot and spread hotness if there is something spawned on them, and then use this as an inverted probability map, instead of a perlin noise.

f) another random sampler you might use could be a Marsaglia polar algorithm which samples from a Gaussian distribution, that yields naturally-looking splotches of probability similar to how shotgun scatter works. this is far superior to trivial noise, and simpler than Poisson disc, and likely gives a better distribution pattern than (d)

g) while we’re at it, you could fix [d] into `chance = (perlin - threshold) / (1 - threshold)` which would normalize the perlin noise below the threshold into heat map. not sure how useful it is, but illustrates how much you can play with many aspects of perlin noise in this regard. this is basically an inverselerp that lets you modulate the noise and flatten out certain peaks (or valleys) if you so desire.

and so on, I could do this for ages.