I took a break from making art this weekend, and tackled something else that’s been in my backlog for a little while: flying enemies!
In Eldritch (and NEON STRUCT), pathfinding was performed on the voxel grid. And because the voxel grid is volumetric, I was able to use it for both flying paths and ground-based paths. The AI motion controller for flight was a little janky, but it served well enough for the small number of flying enemies in those games.
When I switched to a mesh- and navmesh-based workflow for Slayer Shock, I accepted that I wouldn’t be able to do flying enemies anymore, because my navmesh is not a volumetric structure and doesn’t provide enough information to build correct flight paths. So I designed around its absence, and I’ve lived with that constraint on every game or game jam I’ve made in the past decade. But Eldritch 2 really should have flying enemies, if only because the first game did, and it’s been in my backlog for almost as long as the project has existed.
I briefly considered building a voxel representation of the world to use only for flying paths, but I wasn’t keen on adding yet another big data structure to my worlds. The levels in Eldritch 2 are much larger than the first game, and still procedurally generated, so the voxelization process would have to be done at runtime. It might have been possible, but it felt like an exorbitant cost.
Instead, I decided to try reusing the ground-based navmesh for flying paths, and then shortcutting the path wherever possible. Although I don’t have a fully volumetric navigation structure, I do know the approximate ceiling height of each node in the navmesh; it turns out that provides enough information to let flying enemies float high above the ground when they can, but swoop down to ground level to pass through doorways and other shallow passages. And while the pathfinder still routes around chasms which would be impassable to a ground-based enemy, the flight motion controller can shortcut the path if it has direct clearance to its destination. It’s not a perfect solution, and it comes with the small added cost of a sweep check per tick per flying enemy, but… it works. There were a lot of edge cases to fix up, and it still feels like a bit of a hack, but it works.
Now I need to decide what my first flying enemy should be. The flying eyeballs in Eldritch weren’t especially Lovecraftian, but they’re a big part of that game’s flavor, and they were kind of novel as an enemy that couldn’t hear the player. Or maybe I’ll start with night-gaunts this time. Either way… back to making art!