Spawning Logic Rework - Antonio Roldan



Over the past couple of days, as we've been testing out some of our gameplay, there were quite a few bugs still persisting regarding the spawning of my enemies. On rare occasions the enemies would spawn from various spawn points instead of the desired behavior of just spawning from one spawn point at a time. There were also issues with the smoke particle effect I added to each spawn point playing endlessly, when it was supposed to play as an indicator for when enemies spawn. There were other smaller bugs as well but all of this lead me to reassessing my spawn manager and how spawning was being handled in general. 

The current system I had in place was one that was unnecessarily complex and included an entire nested hierarchy of timers that would trigger one another. It took me until now to realize how problematic and finicky handling spawns this way could be, due to race conditions, misaligned timers, and the potential for entire chunks of logic to be skipped. It was clear that this was something I should address, and to do that I needed a system that was much more modular and scalable. I ended up going with the creation of a state machine within my spawn manager as a solution. With spawning logic being state driven what we can do is ensure that logic is running only when in controlled states, and those states can all be controlled by one shared timer that gets reused anytime we transition to a new state. This will eliminate the possibility of race conditions or missed timers because we are only using one timer and our state machine is handling when and where to run logic for the duration of the timer. 


To get started on my state machine I had to consider what states we need. Currently we really only need two but I created an enum with a switch statement anyways to make this design scalable. The two states I need are "WaitingToSpawn" and "SpawningHorde", where the first will be the state we are in between spawns of hordes, and the second will be the state we are in when we are spawning the individual enemies in the horde. The engine behind how these states transition between one another will be a timer that will call our main function after a set duration called "ManageSpawnStates". This is where our switch statement will live, and so when we begin we set our state to WaitingToSpawn, and set our timer to the "HordeInterval", which is the time in between hordes. Once that timer expires "ManageSpawnStates" gets called and since we are in the "WaitingToSpawn" state, we call our function "PrepareToSpawn", which begins our logic. This function first checks to make sure we're not past the spawn limit, then changes our state to "SpawningHorde", gets a random spawn point to spawn our horde from, starts the smoke particle effect at that point, and invalidates the current timer and resets it with my "SmokeTimer", which is how long the smoke should play before calling "ManageStates" again. 


From here we are now in our "SpawningHorde" state so when our main function gets called after the smoke timer expires we enter that state and call our "SpawnHorde" function which does exactly what you think it would.  Inside this function we get a random number in between a minimum and a maximum that we set for the "HordeSize" and we start keeping track of how many enemies we have spawned. Once we have spawned the number of enemies that was chosen, we switch our state back to "WaitingToSpawn", stop our smoke particle system, and again reset the timer to the original "HordeInterval", and the entire thing loops. 

I also wanted to keep the previous functionality I created for ramping up enemy spawns as the player progressed in the mission, so I achieved that by again binding a function to a delegate in the game state, which essentially just reduces the horde interval by a factor every 25% of the mission that the players complete. With all of that done the rework was a great addition that made this logic much more scalable, user friendly and predictable. 

Leave a comment

Log in with itch.io to leave a comment.