This is a massive, rage-inducing WTF moment. I kept having problems with the pathfinding code marking corridors as impassable even though there was enough room to walk along them, and having issues with checking underneath objects, particularly in buildsings with more than one floor. I decided to try updating my pathfinding code in Spamocalypse to use the latest version in my repository, mainly because that allows me to store the navigation data in a ScriptableObject. I thought of using separate meshes for separate floors, or possibly separate rooms, but I then ran into an issue where the dictionaries weren’t being set up on load, resulting in NPCs not being able to find a path and thus trying to walk through obstacles.
I’ve been using this code for around 18 months now. The reason I started using it is because I first started the project on Unity 4.6, when pathfinding was only available to Pro users, and for my thesis project I built/adapted a pathfinding system to track where units died in a team deathmatch game. The way it works is that I cast rays downwards at regular intervals to check if an NPC can walk at that position, and store the result. The only problem is that casting at regular intervals doesn’t really work with arbitrary shapes like those in a real-world city, especially if there are floors below it. So, a few weeks ago I started considering just using the built-in pathfinding system, but I kept putting it off because I thought that refactoring it would take too long…and I didn’t want my code to go to waste. The sunk cost fallacy rears its ugly head!
Now that I have that out of the way, this afternoon I just sat down and tried it. It took me less than an hour to replace my pathfinding code with the built-in NavMeshAgent. So, here’s how the AI works. I should really have done this from the start…
- The main class is still the SpammerFSM class, with bots and Mods being controlled by their respective subclass that overrides their search and attack mechanisms. This still handles the high-level stuff such as how long alerts last, when to attack, etc.
- The MoveAgent class now includes a NavMeshAgent, which is what Unity uses to find paths, and handles movement in the background.
- The LineOfSight class still handles line-of-sight checks. This doesn’t bother tracking live NPCs any more, but will trigger an alert if it finds a corpse.
- The SoundDetection class has not changed. It just listens for the player’s footsteps and other alert sounds (glass breaking, sockpuppet noises, etc). I may change this to account for obstacles between the NPC and sounds, but that’s a different idea.
I still think my code might be useful for other projects, just not for a first-person stealther. If anything, I think it would work quite well for any game with turn-based tactics, where you need to move units to specific positions. Since I’m considering making a Jagged Alliance 2-style game, I may end up using it for that.