Its been a busy few months, between the end of the last blog and November I’ve been working on the first pass of my Utility Based AI.
I used the node editor I created in the previous blog to setup the tools for the UBAI which the first pass can be seen in the screen shot below

So my UBAI is based on a Infinite Axis Utility System created by Dave Mark and Mike Lewis (Building a Better Centaur: AI at Massive Scale (GDC AI Summit Lecture) « IA on AI (intrinsicalgorithm.com))
My adaptation on this is to have a utility reasoner, this contains a list of considerations for running an action, each consideration contains one more more axis that define some knowledge about the game world.
Each consideration will add up the total scores from each axis, and the actions who consideration with the highest score is then run.
A consideration in this case decides if a action attached to it should run. It makes this decision by gathering the information from the Axis and totalling them up. An axis is some knowledge about the game world complied into a normalized value. Each axis will have a response curve, these will add some fuzziness to the result as well as making the appear more natural. For example tiredness ramping up over time.
So back to the screen shot you can see the tool is split up into two panels, the left is where we set up the utility reasoner, the right consists of the list of actions and list of axis the reasoner can use.
Adding actions and new axis to the lists is as simple as just making a class that inherits from either UTAxis or UTAction, the setup for the food axis can be seen below.
public class Food : UTAxis
{
public Food()
{
NAME = "Food";
}
public override float GetValue()
{
if ( _brain )
{
Ball_Agent brain = ( Ball_Agent )_brain;
return brain.data.hunger_need;
}
return .0f;
}
}
GetValue will be passed through the utility response curve as show in the screenshot above.
The get food action looks like below
public class GetFood : UTAction
{
float _waitTime = 5.0f;
public GetFood()
{
NAME = "Get and eat food";
ID = (int)ACTIONS.GET_FOOD;
}
public override bool Update()
{
Ball_Agent brain = ( Ball_Agent )BRAIN;
if ( brain.IsAtDestination() )
{
_waitTime -= Time.deltaTime;
if ( _waitTime <= .0f )
{
// we are done
return true;
}
}
return false;
}
public void Reset()
{
Ball_Agent brain = ( Ball_Agent )BRAIN;
brain.MoveTo( SmartObject_Collection.Food[0].transform.position );
_waitTime = 5.0f;
}
}
If you look in the constructor of the action you will see it has several attributes, NAME and ID, they also have one more CAN_BE_INTERRUPTED. Setting this to true will mean any other action that is scored more than this will be run with out waiting for this one to finish. These attributes will be expanded over the course of the project and exposed to the editor.
Below is a gif showing how this reasoner was made with in the editor. (To better see the gif right click and open in a new tab)

Selecting the reasoner for the agent is simple. Just create an agent brain that inherits from Utility Brain class. In the inspector you should see a drop down list of the reasoners that have been created just pick the one you want attached to this agent.

And that’s basically it, the agent will then go on patrol, feed when its hungry, sleep when its tired.

So what’s next, well the reasoners need more logic for handling multiple actions at once, branching off and running other reasoners etc. There are a few bugs that need fixing and the editor could do with a clean up. So that’s next on my list along with writing up my work for the end of year review.
After that it will be setting up character architypes as well as setting up a more complex game like environment.
See you all next time 🙂