Utility Selector
The Utility Selector task evaluates the child tasks using Utility Theory AI. The Utility Selector is based on the implementation suggested by the Game AI Pro book. The task with the highest utility value will be selected and the existing running task will be aborted. The Utility Selector task reevaluates its children every tick.
The Utility Variable Evaluate returns a utility value based on a constant float value. In the example above the leftmost branch has a utility value of 1, middle has a value of 3, and rightmost has a utility value of 2. The middle branch is selected because it has the highest utility value.
This is the same tree as the first image. The Wait task completed and return a status of success. The Utility Selector acts similar to the Selector task in that it will return success as soon as the first child returns success. Because the middle branch returned success theĀ Utility Selector returned a success.
This example is similar to the first tree, except instead of the middle branch returning success it returns failure. The middle branch executed first because of the utility value of 3, but because it returned failure the Utility Selector moved onto the next highest branch which is the rightmost branch.
Continuing from the last image, the rightmost branch returns success after 1 second and because of that success the Utility Selector then returns success.
Similar to the Selector task, if all of the children return failure then the Utility Selector will also return failure.
The Utility Selector is a responsive task. In this screenshot the second branch is selected because it has the highest utility value of 3.
Every tick the utility value of all of the branches update. The Utility Curve Evaluator will evaluate a curve based on the time elapsed. With each tick the utility value will update and after 10 seconds the third branch has a higher utility value than the second branch. The third branch aborts the second branch even though it hasn’t completed because it has a higher utility value. This is the default functionality but on the Utility Evaluator task you can select Block During Execution which will prevent the branch from being aborted even if another branch returns a higher utility value.
The utility value doesn’t stop updating until the Utility Selector ends. The first branch aborts the third branch because its utility value eventually gets to be higher than the third branch.
Utility Value
Behavior Designer includes two Utility Evaluators:
- Utility Variable Evaluator: Returns a utility value based on a float SharedVariable.
- Utility Curve Evaluator: Returns a utility value based on a curve.
If you want to return a different utility value based on another evaluator you can inherit the Utility Evaluator abstract class. The only method that you need to implement is the GetUtilityValue method:
using Opsive.BehaviorDesigner.Runtime.Tasks.Decorators; public class MyUtilityEvaluator : UtilityEvaluator { /// <summary> /// Returns the utility of the decorator. The higher the utility the more likely the task will run next. /// </summary> /// <returns>The utility of the decorator.</returns> public override float GetUtilityValue() { return 5; } }
The sample class overrides the GetUtilityValue and returns a constant 5 value.