Overhauling Spawn System Architecture

As we saw in that amazing pull request from a bit ago, the spawn system is critical to how the game plays.

As I have heard many other people say, and recently experienced firsthand while trying to make the cloudless thrive prototype, is that it’s complex and challenging to work with.

I want to talk about creating a new architecture for it to allow such a critical part of the game to be tweaked and improved easier.

As I’ve seen a lot in the code base, areas get buried in technical debt to the point only one or two people can actually work on them. We need to work to start scrubbing much of that debt away.

1 Like

The end goal for behaviour of the spawn system is described by a long time open issue:

I link the post that was mentioned there: The Microbe Spawn System

If the goal of this thread is to plan out a new architecture, I think the first step would be getting a grasp of the old one. In particular, I think we can all agree that the compound clouds are the biggest unknown here, so I would start with digging into that code, trying to get a handle of what’s going on, then refactoring just the clouds to something more maintainable. After that, the spawn system at large will likely become a lot more manageable.

Yep. The goal of this thread really is architecture, making it into something maintainable. Though since we would be re-writing a lot of code anyway, implementing some ideas in that gameplay thread wouldn’t be a horrible idea.

I really don’t understand the current architecture despite reading through it several times. Is there anyone here that is familiar with the spawn system? Having someone that already knows it would be very useful here.

Now that I’m back from my break, I guess I’ll reply.

So here’s the outline for how it works:

  • PatchManager runs to update the registered spawners in SpawnSystem by calling AddSpawnType with a Spawner derived object for example ChunkSpawner or MicrobeSpawner
  • The SpawnSystem then runs on a short timer (just to save some performance) and each time it runs it does a few things:
  • Spawns any queued objects (this is to reduce lag spikes by spawning only a limited number of things per frame)
  • If only a little time is elapsed then only despawning things is checked. Despawning happens based on distance to the player (if too far away), and there’s also a despawn limit per frame
  • Otherwise if enough time has elapsed the SpawnSystem starts a spawn cycle
    • The first thing that does is it removes spawner types that are deleted by the PatchManager to not spawn those anymore
    • Then the spawn system creates a grid of sectors, and for each sector that has not been processed before (the processed sectors are saved in a list that is cleared only when switching patches), and does the following:
      • Go through each spawner (skipping spawners that are constrained by entity limit if we already have too many entities) and try to spawn stuff with it. Note that the loop is not broken if we exceed the limit of stuff to spawn so that the sector stuff spawns more fully. The spawners are went through in order so that each type gets chance to spawn (in other sectors if current is full). Once all spawners have been used once, the list is shuffled.
    • Finally the patch system specifically goes through only microbe spawners trying to spawn one by one from those around the player (once all types are spawned the order to spawn is randomized)
  • Additionally the above would result in the game lagging a lot due to spawning too much, so the spawn system prevents spawners that create entities from spawning stuff when the game is over the entity limit. And as I mentioned above spawns can be queued so that a spawner that wants to spawn multiple things is actually put in a queue which is processed on subsequent frames.

Overall I think it is actually very simple, but due to the randomness in the system, getting specific results out of it isn’t really possible.

The goal of the encounter based system would be to basically keep the spawn setup stuff the same, but instead of randomly spawning with the specific spawners, the registered spawners would create interesting encounters at grid points. That way the player would experience stuff at certain intervals and maybe we could fudge the statistics / have a counter to make sure that enough different types of encounters spawn often enough. The encounter concept is basically that just instead of each spawner spawning like one cloud, one microbe, or 4 microbes in a colony arrangement, the spawner would spawn like 3 compounds clouds, 2 chunks, and 5 enemy microbes clustered together pretty closely.

Well a few comments now that I went through the code, the SpawnMicrobesAroundPlayer is pretty bad in my opinion. It fills up the entity limit from stuff that isn’t in the sectors. So I think one easy improvement could be done:

  • SpawnMicrobesAroundPlayer would only run when there’s like 20% or 10% entity limit left, that gives more room for the sector spawning

Seeing as no one replied, I opened that one issue I thought could improve the situation a bit: