DevLog 09 - Enemy State Machine


Enemy Behavior

For this DevLog, I wanted to share another video explaining my process of how I reached this stage and show you some of the different elements I had to work out.

But essentially, this DevLog is all about Enemy behavior and building my first working State Machine. I still don't fully understand how a state machine is managed. I understand how it moves from one state to another, but I'm still confused about the State Machine script itself and how it helps manage the transition from one state to the next. It's hard to visualize.

But in any case, I had attempted to build an Enemy state machine back in March and April when I last worked heavily on the initial test level that you saw in DevLog 08. I had been following a tutorial from Zenva about creating enemy state machines, but for some reason, the machine I had built was not functioning correctly and was exhibiting unusual and unexpected behavior. So I felt I needed to start fresh in a separate, isolated project and build the state machine there. Even when I followed along to a T, the state machine still didn't function as expected. So I actually went line by line and compared my code to the code from the tutorial's finished project file, and that's where I discovered several minor inconsistencies that, once addressed, allowed the code to behave as intended. 

Current State Machine

When I built the first working state machine for my White Rabbit enemy, I had used unique references to a "RabbitController" script, and a VAR for a "rabbit" root node. But once I wanted to add a 2nd enemy to my test scene, I realized that I could make the entire enemy script and its state machines scripts universal between all enemy types. I would just need to make all references generic, and then only change the name of the Root Node itself to differentiate between the enemies visually. But now all scripts could be shared between all enemies. 

There are a few cases where the Controller script will need to be modified in a way to allow for unique behavior on a few floating/flying enemies. So I'll need to decide whether the script will need to be unique, or whether I'll need to create a few special functions that only activate if a boolean is set to True in the inspector. 

But for now, the current State Machine includes the following items:

  • Walking / Wander state
  • Chase state
  • Attack state
  • Death state

The Walking state allows the enemy to wander about in random directions through the map.

The Chase state is activated if an enemy is within 8 meters of the player or a designated target. 

The Attack state is activated once an enemy is within 1 meter of the player or a designated target. At which point I've added a small bit of code that reduces a Health variable by 1 point every delta time tick. So once an enemy starts attacking, their health will depleat from 100 to 0 in about 3 seconds.


The Death state is activated once an enemy has died. This then triggers an "is_dead" boolean on the enemy's Controller script so that the Collision Layer and Collision Masks are swapped around. I needed this to happen so that the enemies would not fall through the floor, but could pass through each other so they wouldn't pile up next to the target or player. Before I fixed this, the enemies would all bunch up together around the dead enemies, and they would never get close enough to change to the Attack state. The only oddity right now is that the enemies will physically nudge each other out of the way if they all meet at about the same time. I'd prefer it if the Attacking enemy would stay put and the Chasing enemies wouldn't be able to move them. But I figured since the Player character would be trying to dodge and evade several enemies at once and try to pick them off, then this bunching and nudging issue wouldn't actually pose any problems in game.

Future States

In building this Enemy behavior state machine, it occurred to me that this could equally be used to create the Weapon swapping mechanic, since all weapons would use the same mechanics, they would just need to have a State that merely swapped out the textures and the ammo type/ammo power. But those individual states could all extend from a base State class that would define all Weapon functionality. I'm not sure if a single entity can have multiple state machines operating in tandem, but I don't think I'll need to worry about that in this case, since the Player movement is already handled in a standard way.

I had considered if the weapons would need to be picked-up and added to an inventory with a full inventory system. But I think a simple series of Checks and Bools will do just fine to keep track if a weapon has been picked-up and is now available in a swappable or choosable list. 

But in thinking about what the Weapons would need to do, it made me realize that the Enemies will still need at least 1 more state, along with some additional code in the current states. 

The missing 5th state is a Hit state, where the Enemy is hit by the player and is stunned for a brief moment before coming back into Attack or Chase state. This gives the player a chance to keep hitting or shooting the enemies without getting hit themselves.

The missing code is something that I think needs to be added to the Chase state, where, if the enemy entity is stalled for too long without changing to another state, it should automatically revert to the Walking state. Similarly, I'd also like the enemy entity to have a Raycaster that allows it to know when it physically sees the Player within an 8 meter range, and when it does not see the Player. So if a wall or other object obscures its line of sight, it's behavior will be modified to either stop cold, or go on a chase timer before losing interest and reverting to Walking again.


So my next major task will be the Weapon state machine. As I'm building this, I'll be implementing the Ammo pick-ups, Ammo counter, Ammo power level, projectile fruits, fruit splats, enemy deaths, and possibly environment decals. Once I have the ammo pick-ups created, this will also give me the base code to extend into other pick-up items, including the Next Level keys and False keys for each level.

That's next on DevLog 10.

Leave a comment

Log in with itch.io to leave a comment.