Kalia and the Goblin AI


Hello all! Today I wanted to get into detail on recent implementations for the third chapter of the KatFS demo regarding enemy AI. For those out of the loop, the first two chapter of the demo featured enemies with simple behaviors by design, such as zombies that simply shamble towards the player mindlessly, or spiders that wander around in swarms without an specific destination in mind. For the third and final chapter of this demo/prototype, my intention has been to take enemy AI up a notch and introduce a new category of creatures that exhibit smarter behaviors - the goblins!

This will be a long devlog, which I'll divide into three sections: Rogues (Stalking and Dodging)Snipers (Cover Seeking) and Dynamic Navmesh Experiments. Let's go!

SECTION 1 - ROGUES (STALKING AND DODGING)

Let's start with the rogues, who have pretty much all of their core behaviors implemented already. As a reminder, these guys will approach Kalia and stalk her from a distance, before charging in for an attack and immediately rolling away after. They will also attempt to dodge away from certain attacks. But why read about it when you can witness it?

So let's break down the goblin's behavior into parts. Upon detecting the player, the goblin will enter chase mode, where it will simply path directly towards their target, not unlike how the skeletons or zombies behave. However, once they are within a set stalking distance from the player, they will enter their next phase: stalk.


Stalking is where the rogue's behavior gets complex. The intended outcome is that the rogue attempts to remain within a set distance of the player while also never standing still. My solution for this has been to have the goblin path in a circle around their target. To prevent the rogue from running into a wall, it will also check if the next portion of the circle is actually pathable, and reverse course if not.

After enough stalking time, the rogue will then enter its charge phase, pathing directly to its target with increased speed, and finally making its attack. But what about dodging? The rogue can dodge melee attacks reactively, only doing so after it's been hit with one. But in order to make it dodge projectiles proactively, the projectile code had to be upgraded, firing a ray on its path that communicates every AI it hits that a projectile is incoming. Currently, only the rogue reacts to this information, dodging in a random direction perpendicular to the projectile.

SECTION 2 - SNIPERS (COVER SEEKING)

The goblin snipers are currently under active development, but their cover-seeking behavior is already functional, so that's what I'll be writing about in this devlog. When not aiming their shots, these goblins will seek to hide behind rubble and buildings to avoid return fire.

In order to get this system working, rather than creating a fancy cover detection algorithm that would take a month to get right, I opted for a simple approach - just mark down the spots where the goblins (and any other future enemy type) can take cover in. However, rather than manually placing down markers, why not add such markers to the prefabs that get used everywhere in the game so that they're placed down automatically? And so, all existing scenes automatically got their cover markers placed down.

Some auxiliary systems were also put in place to make these markers smarter. Since they're child objects to their prefab, that means they work for dynamic objects (move a crate and the AI will know to take cover where it is currently). To invalidate cover points that end up inside other colliders, a basic check against the navmesh can be made, automatically invalidating these markers and revalidating it should they become pathable due to a change in the environment. And finally, the AI scripts can access the parent object of a cover marker for additional sanity checks (such as checking whether a potential cover object is on fire, and skipping it).

With the markers in place, it's still required to check if they actually function as cover against the player's current position. This wasn't that difficult to figure out either: just fire a raycast from each marker to Kalia and check if the first collider hit belongs to the marker's parent object. If it does, that means it stands between the marker and Kalia, and thus makes that marker viable as cover!

SECTION 3 - DYNAMIC NAVMESH EXPERIMENTS

This section will be part a preview of a future mechanic and part me rambling about an implementation that has hit a technical dead end for the time being. When developing the spiders in chapter 2, an important aspect of their behavior was their active avoidance of fires. Since the spiders used a "boids" style algorithm, it was just a matter of gathering information about nearby fires and using them as "repulsors" when calculating their path.

The goblins being supposedly smarter than the spiders, they should probably feature a similar kind of fire-avoidance behavior. However, goblins use Unity's NavMesh and Agent components for their pathfinding, meaning that the spider approach isn't entirely compatible with how they navigate the level. Researching ways to achieve this goal, it seemed that the answer was to use NavMesh layers to denote which areas of the level are "fire hazards". This seemed brilliant! Not only would the goblins be able to navigate around fires, but they would even be able to weight choices such as running through a fiery shortcut vs going the long way around something.

However, there was a major hurdle that I've not yet managed to overcome to get this solution to work. This method requires the NavMesh to be updated whenever a fire starts, ends or gets moved. And updating a NavMesh is a costly operation - tests in the demo chapter 2 resulted in a noticeable chug whenever the NavMesh had to be updated. Considering how frequently that would be, it would impact the feel of the game negatively.

And so the search for a solution began. See, a major issue is that KatFS currently uses an experimental 2D NavMesh package, meaning that the "official" solutions wouldn't necessarily be compatible. Not that I could find much on the way of official solutions anyway, as detailed information and examples on Unity's NavMeshes seems to be lacking somewhat online. The most promising solution so far has been to use specific parameters that allow only a portion of a NavMesh to be updated rather than the entire thing, but I haven't been able to get it to work in KatFS. Other potential solutions could be to limit the NavMesh to only a portion around Kalia, or to possibly offload this operation to a separate thread, but these have yet to be attempted.

Most likely, this feature will be shelved until after the demo is done and KatFS enters alpha. Which is a bummer, but is what it is. I'm open to suggestions though! :']

That will be all for this devlog! This week, the sniper AI should be finished and work on the mage and cleric can begin. While I cannot give a date yet, I'm certain that the third and final chapter of the KatFS pre-alpha demo will be releasing sometime later this year. Until the next devlog!

Get Kalia and The Fire Staff Pre-Alpha

Download NowName your own price

Comments

Log in with itch.io to leave a comment.

Great progress on the Goblin AI!! I like it!! And yes, AI can be hard to do… But don’t worry, I’m sure you will accomplish it :D Good luck!!