Posted July 23, 2020 by void room
What would be a shooter without enemies?
In games that have hand-made levels, most of the times, enemies are also placed by hand. This approach allows for creating more directed encounters. Gives some control over pacing and tension. Creates dynamic in the level/arena.
When enemies are spawned and when do they start to actually do something? It depends on the game. Sometimes they are spawned only when you enter an area or about to enter it. You may perceive them as they were always there but they do come into the existence only a few moments before you see them.
This is done to have the same starting point of an encounter, if you failed and you try again or if you play the game again. If the enemies were just left to do whatever they want, they could wander off to seek for something. Or could start fighting each other. And actually, these kinds of things were happening in Tea For God. If you ever encountered a gun laying on the ground or an energy orb. It was not just placed there. There was a robot that was killed by some other robot.
Back to spawning systems.
With procedurally generated levels, arenas especially, you may still define places with a particular purpose. Higher ground, risky passage, open area with a valuable item in the middle, etc. While you can't place each enemy by hand, you can have a simple system that uses those places to spawn enemies according to a prepared scenario. Start with a mini-boss in the middle, weaker enemies around him. If a mini-boss is defeated, another one enters and so on.
I have a system that works similar to this. You can check it out at the elevator bridge. When you enter the room/bridge, enemies are spawn and transferred to the arena using drop capsules (with a 3-second delay). As soon as they all are killed, the timer is started and after ten seconds another wave starts. Second and all consecutive waves have fewer enemies than the first one. They are also dropped in front of you in a specific distance - if that's possible. If not, they are kept at a distance but may land behind you.
Things get much more complicated when you add impossible spaces here and limited to a play area. Knowing that many people won't have more than 2x2 metres. It makes it not so easy to direct and encounter in narrow and twisted corridors. Especially with branching. I have still no idea how to spice the things up (other than by use of spawning more aggressive enemies and mini-bosses). I will have to come up eventually.
There is also another problem.
Before 0.4.13, all the enemies were just spawned into the level right when it started (except for the already mentioned elevator bridge). They were walking around, fighting each other (they are/were quite aggressive towards each other, just bumping into another robot could lead to a fight).
Having 30 or 40 creatures walking around leads to a higher CPU use which may affect the framerate. That's one reason to not spawn all the enemies right away.
Another one is that if you walk through the level, you may end up with no enemies. Because you killed them. Because they went somewhere else. That's another reason.
And as I want to have an open world, I can't just spawn the enemies, let them wander off and then somehow track if I should spawn the same enemies in the same places.
All those reasons resulted in a dynamic spawning system.
When it decides to spawn a robot (more on when that happens later), it finds a spot using placement criteria (like it has to be near the player, there has to be enough room to spawn a character and so on, it might be also in a specific distance from other robots). It may also give a hint to the spawned robot, where it should go to encounter the player. The AI won't know that the player is there. It has to see the player to register and decide what to do (and oh there are some issues with that, like some robots may walk past you and they won't notice you because you fell out of their FOV etc.).
I used to choose "not visible" spawn point if it was just not in the rendered view. After having a few enemies spawn right behind my back, decided to change that to all-around.
The dynamic spawning system also decides whether to give up a particular robot. If it's too far away from the player, it might be better to despawn it and have a slot for another one.
One missing bit of the dynamic spawning system is when should characters get spawned. I decided to use a similar approach as I have with waves for the elevator bridge. If enough characters are killed, there's some cooldown before they start spawning again. But contrary to the elevator bridge, after a few waves, it may end. This means that it is possible to clear an area. I don't know if it's worth having a longer cooldown to restart the waves after 20 or 30 minutes as I'd like to make the open-world push you forwards (by cutting off rooms and corridors so you will eventually move forward) and not just let walk around the very same zone for hours.
There might be multiple spawning pools to make it possible to get rid of the hostiles while the neutral robots are still there. Or you could kill all the neutral robots. At the moment I have only two pools: guards and neutral.
I'd like to add another layer/AI manager that could control dynamic spawn manager to have better overall control on pacing. Especially when narrative elements will be added.
To develop dynamic spawning system further, I need to implement the open-world feature. To see how it works, what has to be changed, added, removed, etc.