Goal-oriented behaviors are a set of techniques aimed at giving agents not only a sense of intelligence, but also a sense of free will, once a goal is defined, and given a set of rules to choose from.
Imagine that we're developing a trooper agent that needs to only reach the endpoint of capturing the flag (the main goal), while taking care of its life and ammo (the inner goals for reaching the first). One way of implementing it is by using a general-purpose algorithm for handling goals, so the agent develops something similar to free will.
We will learn how to create a goal-based action selector that chooses an action considering the main goal, avoids unintentional actions with disrupting effects, and takes an action's duration into account. Just like the previous recipe, this requires the modeling of goals in terms of numerical values.
Along with the action chooser, we will create base classes for actions and goals:
using UnityEngine; using System.Collections; public class ActionGOB : MonoBehaviour { public virtual float GetGoalChange(GoalGOB goal) { return 0f; } public virtual float GetDuration() { return 0f; } }
GoalGOB
parent class with member functions:using UnityEngine; using System.Collections; public class GoalGOB { public string name; public float value; public float change; }
public virtual float GetDiscontentment(float newValue) { return newValue * newValue; } public virtual float GetChange() { return 0f; }
ActionChooser
class:using UnityEngine; using System.Collections; public class ActionChooser : MonoBehaviour { }
public float CalculateDiscontentment(ActionGOB action, GoalGOB[] goals) { float discontentment = 0; foreach (GoalGOB goal in goals) { float newValue = goal.value + action.GetGoalChange(goal); newValue += action.GetDuration() * goal.GetChange(); discontentment += goal.GetDiscontentment(newValue); } return discontentment; }
public ActionGOB Choose(ActionGOB[] actions, GoalGOB[] goals) { ActionGOB bestAction; bestAction = actions[0]; float bestValue = CalculateDiscontentment(actions[0], goals); float value; // next steps }
foreach (ActionGOB action in actions) { value = CalculateDiscontentment(action, goals); if (value < bestValue) { bestValue = value; bestAction = action; } }
return bestAction;
The discontentment functions help avoid unintended actions, depending on how much a goal's value changes, in terms of an action and the time it takes to be executed. Then, the function for choosing an action is taken care of by computing the most promising one in terms of the minimum impact (discontentment).