I presume that your main issue is with the IsTimeToSpawn function:
bool IsTimeToSpawn(GameObject attackerGameObject)
{
Attacker attacker = attackerGameObject.GetComponent<Attacker>();
float meanSpawnDelay = attacker.seenEverySeconds;
float spawnsPerSecond = 1 / meanSpawnDelay;
if (Time.deltaTime > meanSpawnDelay)
{
Debug.LogWarning("Spawn rate capped by frame rate");
}
float threshold = spawnsPerSecond * Time.deltaTime / 5;
if (Random.value < threshold)
{
return true;
}
else
{
return false;
}
}
So let’s break it down.
First we get the Attacker component of the prefab we passed in as a public variable:
Attacker attacker = attackerGameObject.GetComponent<Attacker>();
This allows us to get to its public seenEverySeconds variable, for which we make a new local variable called meanSpawnDelay:
float meanSpawnDelay = attacker.seenEverySeconds;
But what we want is the spawn rate, or the number of times this attacker spawns per second, which is just the inverse of the spawn delay:
float spawnsPerSecond = 1 / meanSpawnDelay;
Now the interesting part. We define a threshold
float threshold = spawnsPerSecond * Time.deltaTime / 5;
Time.deltaTime gives us the time since the last frame (so at 60 fps, it is 1/60th of a second). Multiply that by the times we spawn an attacker every second (let’s say 1/10 for an attacker every 10 seconds), and we get the probability that an attacker will be spawned this frame (1/600). Then we divide that probability by the number of spawners in our scene, so that 1 of those attackers spawns on average every 10 seconds overall.
Finally, we compare that probability to a random value. If the probability is 0.5, there is a 0.5 chance that a random value will be lower than it. If it is 1/3000, there is a 1 in 3000 chance that a random value will be lower than it, etc. So we simply say, at every frame, if that random value is lower than our calculated probability, spawn an attacker.
if (Random.value < threshold)
{
return true;
}
else
{
return false;
}