- Home /
Generating Objects at High Speeds
Hey everyone!
I'm having an issue with generating objects at variable speeds in my game. Currently, I am generating a vertical "line" of game objects every so often at a set speed, which works fine, as long as the speed isn't too high. However, if I adjust the speed so that it is higher, and/or temporarily increase the speed and slow it back down via a coroutine, the objects will start generating inconsistently and spaced out instead of at the same consistent rate. To illustrate this problem, here is how the game looks (scene view top, game view bottom) before the coroutine is started:
And here is how it looks like after the coroutine is started and ended:
(Weirdly, the first column of the generated objects appears warped, so I'm not sure what's going on there. Could be an unrelated issue.)
I first thought this was due to not taking into account the speed modifier during the coroutine when generation happens, so I tried applying that the values that seemed relevant, but that didn't work (also, the problem only seems to happen after the coroutine completes, making me believe that this might not be the issue).
I'm reusing instantiated objects: the game will instantiate new objects if it can't find any within the pool, and if it can, it will simply reactivate them and use them again.
Here's the object generation code as well as the speed up coroutine.
private void OnDespawn(PoolableObject poolable)
{
if (poolable is NPCLine)
{
//This is throwing an invalidoperationexception when it goes too fast
// NPCLine despawnedLine = poolable as NPCLine;
// var item = npcLineMatrix.First(kvp => kvp.Value == despawnedLine);
// npcLineMatrix.Remove(item.Key);
}
}
//This coroutine is pretty clunky as-is; there's probably a better way to achieve the effect
IEnumerator BasicAttack()
{
float timer = 0f;
float t = 0f;
float minimum = 1f;
float maximum = 4f;
float partOne = 1f;
float partTwo = 2f;
float partThree = 3f;
invulnerable = true;
moveSpeedAttackMultiplier = 1f;
while (timer < partOne)
{
moveSpeedAttackMultiplier = Mathf.Lerp(minimum, maximum, Mathf.SmoothStep(0.0f, 1.0f, t));
timer += Time.deltaTime;
t += Time.deltaTime;
yield return null;
}
moveSpeedAttackMultiplier = maximum;
while (timer < partTwo)
{
timer += Time.deltaTime;
yield return null;
}
float temp = maximum;
maximum = minimum;
minimum = temp;
t = 0f;
while (timer < partThree)
{
moveSpeedAttackMultiplier = Mathf.Lerp(minimum, maximum, Mathf.SmoothStep(0.0f, 1.0f, t));
timer += Time.deltaTime;
t += Time.deltaTime;
yield return null;
}
invulnerable = false;
moveSpeedAttackMultiplier = 1f;
yield return null;
}
void OnFixedTick()
{
float timestep = moveSpeed * cameraSize * moveSpeedAttackMultiplier;
this.mRigidBody.velocity = new Vector2(timestep, 0);
if (prepareTimer < ttPrepare)
prepareTimer += Time.deltaTime;// * timestep;
int maxX = npcLineMatrix.Keys.Max();
//If the new position to spawn at is within the horizontal bounds
float spawnX = npcLineMatrix[maxX].transform.position.x + spawnDistanceX;
float specialSpawnY = maxSpecialSpawnY * cameraSize;// * moveSpeedAttackMultiplier;
if (spawnX < this.transform.position.x + (this.baseNPCSpawnMaxX * cameraSize * moveSpeedAttackMultiplier))
SpawnLine(spawnX, false, specialSpawnY);
}
float lastTime;
void SpawnLine(float spawnX, bool neutralOnly, float specialSpawnYMax)
{
if (lastTime != null) Debug.LogError(Time.time - lastTime);
lastTime = Time.time;
float maxY = this.baseLineHeight * cameraSize;// * moveSpeedAttackMultiplier;
if (even) npcLineMatrix.Add(npcLineCount, SpawnEvenLines(spawnX, (int)maxY, neutralOnly, specialSpawnYMax));
else npcLineMatrix.Add(npcLineCount, SpawnOddLines(spawnX, (int)maxY, neutralOnly, specialSpawnYMax));
npcLineCount++;
even = !even;
}
NPCLine SpawnEvenLines(float newX, int newMaxY, bool neutralOnly, float specialSpawnYMax)
{
// Debug.LogError("spawning even line at " + newX);
NPCLine newLine = Pool.SpawnNewNPCLine(new Vector3(newX, 0, 0));
newLine.transform.position = new Vector3(newX, 0, 0);
for (int i = -newMaxY + 1; i < newMaxY; i += 2)
{
if (neutralOnly || prepareTimer < ttPrepare || Mathf.Abs(i * spawnDistanceY) > specialSpawnYMax) newLine.SpawnNPC(NPC.NPCState.NEUTRAL, new Vector3(newX, i * spawnDistanceY, i));
else if (!boss && Random.Range(0, 100) < bonusChance) newLine.SpawnNPC(NPC.NPCState.BONUS, new Vector3(newX, i * spawnDistanceY, i));
else if (!boss && Random.Range(0, 100) < grumpChance) newLine.SpawnNPC(NPC.NPCState.GRUMP, new Vector3(newX, i * spawnDistanceY, i));
else newLine.SpawnNPC(NPC.NPCState.NEUTRAL, new Vector3(newX, i * spawnDistanceY, i));
}
return newLine;
}
NPCLine SpawnOddLines(float newX, int newMaxY, bool neutralOnly, float specialSpawnYMax)
{
//Debug.LogError("spawning odd line at " + newX);
NPCLine newLine = Pool.SpawnNewNPCLine(new Vector3(newX, 0, 0));
newLine.transform.position = new Vector3(newX, 0, 0);
for (int i = -newMaxY; i < newMaxY + 1; i += 2)
{
if (neutralOnly || prepareTimer < ttPrepare || Mathf.Abs(i * spawnDistanceY) > specialSpawnYMax) newLine.SpawnNPC(NPC.NPCState.NEUTRAL, new Vector3(newX, i * spawnDistanceY, i));
else if (!boss && Random.Range(0, 100) < bonusChance) newLine.SpawnNPC(NPC.NPCState.BONUS, new Vector3(newX, i * spawnDistanceY, i));
else if (!boss && Random.Range(0, 100) < grumpChance) newLine.SpawnNPC(NPC.NPCState.GRUMP, new Vector3(newX, i * spawnDistanceY, i));
else newLine.SpawnNPC(NPC.NPCState.NEUTRAL, new Vector3(newX, i * spawnDistanceY, i));
}
return newLine;
}
Any advice or help would be greatly appreciated (and I'll happily provide more info if it helps). Thanks in advance! :)