2 - Detection & State Machines


Download Link - BLOCKHEADS_v0.2.0

Overview

So now that the AI is capable of navigating around the map (See Devlog - 1) I felt the natural next step was to give the AI the ability to detect one another. From there I could start to implement unique behaviors based on the detection of different types of BLOCKHEADS.

The above video shows the results of this detection system. Similar to the previous version there are 3 core types of BLOCKHEADS :


WANDER ( BLUE )PATROL ( PURPLE )RUNNER ( YELLOW )RUNNER ( RED )
Wanders around the map until another AI is detected. 

If a YELLOW RUNNER is detected - it attempts to follow it around the map.

if a RED RUNNER is detected - it attempts to flee from it. 


Moves between patrol points until another AI is detected. 

If a YELLOW RUNNER is detected - it attempts to follow it around the map.

if a RED RUNNER is detected - it attempts to flee from it. 


Modified version of Wanderer that runs around the map selection new wander points at an increased rate. 

Ignores detection of all types. 

Other types will FOLLOW if they detect this Runner.
Modified version of Wanderer that runs around the map selection new wander points at an increased rate. 

 Ignores detection of all types. 

 Other types will FLEE if they detect this Runner.

A state machine framework is used to have the Wander and Patrol BLOCKHEADS perform different logic depending on the results of their detection. For now each type is assigned an ID value that dictates what state to transition to:

Lower ID = Follow   |   Same ID = Ignore   |   Higher ID = Flee

This ID system works fine for this stage of implementation, but in the future I'd like to expand the decision making to take in more useful metrics when deciding whether to pursue or flee from a detected target. 


Key Resources


Just like the first devlog, before I get into some development highlights I want to highlight some key resources that helped me reach this update.

Bitlytic - Finite State Machines in Godot 4 in Under 10 Minutes

I highlighted this video in the last devlog, sharing how I used this framework to set the different movement types on the BLOCKHEADS. For this update I continued with this approach, implementing the full setup of a state machine, states, and transitions between states.  I highly recommend this video if your curios about state machines in Godot, its short and to the point while breaking down the concept in an easy to understand way. 


Development Highlights

Flexible State Design

This State Machine framework has been pretty successful in creating unique AI types without needed new code. 

I do this by making the State Machine is its own scene, this way it can be added to any object that needs a state machine. The State Machine gets its States through its children, so I can mix and match any set of states to create unique types. Each state is also its own scene so they can be dropped into any state machine and function as long as references are provided.

Defining State Transitions In Inspector

The state machine setup of Bitlytic's video relies on string variables to pass the state name the machine should transition to. As someone who is both an awful speller and prone to typos, I took some time to develop a workaround where you can define your state transition states in the inspector by simply selecting one of the available states in the scene tree. 

To do this I export a variable of type State for each state transition the current state requires. 


Then I convert that state's name into a string when passing it into the Transitioned signal. 


Not only does this help avoid spelling related code errors, but it also prevents transitions to a state that is not currently a child of the instanced state machine. 

Changing States On Detection

I want to highlight how transitions on detection are handled because I think its a good example of how to approach state transitions in a way that is flexible for all states. 

First the Detection Area sends signals to the State Machine on body enter and on body exit. The State Machine then calls the corresponding transition on the current state.

The base State script has transition methods for detect enter and exit for the state machine to reference.

Then I rewrite these methods in each new state that requires this transition type. 

With this approach the State Machine can call these transition methods on whatever state happens to be the current state, then that state can handle the call to fit it's specific needs. For example the Idle State example above grabs the detected AI's ID value and transitions to the correct state based on that value.


Conclusions & Next Steps

I am very happy with the results of this update. Some unique behaviors between the BLOCKHEADS are starting to emerge even with their limited abilities. The State Machine has lots of room for improvement, the reference setup for each state can be pretty tedious so that's something I'll be looking to refine as I continue. 

I'll be getting into some interesting stuff for the next devlog as I plan to add some basic combat mechanics like attacking, health, and damage between the AI. So make sure to comeback for the next one if your interested.

Thanks for reading!

Leave a comment

Log in with itch.io to leave a comment.