Skip to content

Action Tasks

Action Tasks are the tasks a utility agent executes when the associated decision is selected. They are executed either sequentially or in parallel, depending on the execution mode of the action list.

Execution Modes

After the agent determines the best decision, it will execute the actions either in sequence or in parallel, depending on which execution mode is selected. Currently, there are 3 execution modes:

  • Sequence
    • The actions are executed sequentially.
    • If an action ends in success, the agent will execute the next action.
    • If the last action ends in success, the action list will end in success.
    • If an action ends in failure, the action list will end in failure.
  • Parallel
    • The actions are executed simultaneously.
    • If any action ends in failure, other actions will be aborted and the action list will end in failure.
    • If all actions end in success, the action list will end in success.
  • ParallelComplete
    • The actions are executed simultaneously.
    • If any action ends in success or failure, other actions will be aborted and the action list will return the child status immediately.

You can choose the execution mode you want by selecting it from the action execution dropdown menu in the Decision Tab.

center|600

Max Repeat Count

You can specify how many times the action list is repeated by changing the Max Repeat Count.

center|600

Note

  • The action list repeats only if it ends in success.
  • If MaxRepeatCount <= 0, the action list repeats indefinitely until it ends in failure.

Keep Running Until Finished

To prevent the agent from making a new decision while the action list is running, you can enable the Keep Running Until Finished option.

center|600

Tip

  • Enabling this option for important decisions, such as AttackEnemy, ChargeHealth, and ReloadAmmunition, helps the agent stay focused and not get distracted by less important decisions. This helps reduce oscillation between critical and non-critical decisions.
  • For example, with the AttackEnemy decision, you should enable this option because the agent needs to finish the attack before switching to another decision, such as RunAwayFromEnemy.

Note

  • If you enable this option, the agent can only change its decision after the action list is finished, regardless of whether other decisions have higher scores.
  • For example, with the AttackEnemy decision, the agent can only switch to another decision after the attack is finished, even if other decisions like RunAwayFromEnemy or ReloadAmmunition have higher scores than AttackEnemy.

Creating Action Tasks

  1. To create a new action task, define a new class that inherits from ActionTask:

    public class Wait : ActionTask
    {
        private float elapsedTime;
        public VariableReference<float> WaitTime = 1.0f;
    
        protected override void OnStart()
        {
            elapsedTime = 0;
        }
    
        protected override UpdateStatus OnUpdate(float deltaTime)
        {
            elapsedTime += deltaTime;
    
            if (elapsedTime > WaitTime) return UpdateStatus.Success;
            return UpdateStatus.Running;
        }
    }
    

  2. To assign the action task to a decision, select the decision in the Decision Tab, choose the action type, and then click the Create button:
    Attachments/UtilityIntelligence/Documentation/UtilityAgent/Decisions/assign-action-task.png

Adding Parameter Fields

There are many cases when you need to add parameters to an action task to customize how it works. To achieve this, you need to declare these parameters as public fields in your action tasks. Here are some examples of how to do this:

[Category("Examples")]
public class StartMeleeAttack : ActionTask
{
    public MeleeAttackType AttackType;
    public int AttackDamage;
    public int AttackForce;
    public int ConsumeEnergy;

    public VariableReference<float> AttackRange;
    public VariableReference<int> AttackNumber;
    public VariableReference<string> AttackAnimationName;
}
[Category("Examples")]
public class StartRangedAttack : ActionTask
{
    public RangedAttackType AttackType;
    public int ConsumeEnergy;
    public int AttackDamage;
    public int ProjectileSpeed;
    public float MaxCurvedHeight;
}

Supported Field Types

Currently, only the supported field types can be serialized to JSON and adjusted using the Utility Intelligence Editor. Therefore, you should use these types when declaring parameter fields for your action tasks.

Action Task Statuses

At runtime, action tasks have 4 statuses:

 : Running


 : Success

 : Failed


 : Aborted

Built-in Action Tasks

Currently, Utility Intelligence provides these built-in action tasks:

  • Idle: Does nothing.
    • Always returns UpdateStatus.Running.
  • Log: Logs a message to the console.
  • Wait: Waits until a wait time has passed.
    • The wait time is specified in the WaitTime variable.
    • Returns UpdateStatus.Success when the wait time has passed, otherwise, returns UpdateStatus.Running.
  • RandomWait: Waits until a wait time has passed.
    • The wait time is chosen randomly between the WaitTimeMin and WaitTimeMax variables.
    • Returns UpdateStatus.Success when the wait time has passed, otherwise, returns UpdateStatus.Running.
  • DestroySelf: Safely destroys the current agent.
  • MoveTowardsTarget: Moves to wards the target.
    • Uses Vector3.MoveTowards to move the agent towards the target.
    • Returns UpdateStatus.Success when the agent has reached the target, otherwise, returns UpdateStatus.Running.
  • StartCooldown: Starts a cooldown.
    • The start time of the cooldown is stored in the CooldownStartTime variable, which is used by CooldownElapsedTimeInput and IsInCooldownNormalization to determine if the agent is within the cooldown duration.
  • Animator
    • SetBool: Set the value of the boolean parameter specified by ParamName.
    • SetFloat: Set the value of the float parameter specified by ParamName.
    • SetInteger: Set the value of the integer parameter specified by ParamName.
    • SetTrigger: Set the value of the trigger parameter specified by ParamName.
    • WaitUntilAnimationFinished: Waits until the specified animation is finished.
      • Returns UpdateStatus.Success if the animation specified by AnimationName has the normalized time greater than FinishedNormalizedTime, otherwise, returns UpdateStatus.Running.
  • NavMeshAgent
    • ChaseTarget: Chases the target.
      • The target position is updated every frame.
      • Returns UpdateStatus.Success when the agent has reached the target, otherwise, returns UpdateStatus.Running.
    • MoveToTarget: Moves to the target.
      • The target position is updated only once at the start.
      • Returns UpdateStatus.Success when the agent has reached the target, otherwise, returns UpdateStatus.Running.
    • MoveAwayFromTarget: Moves away from the target.
      • It will choose a destination at a distance specified in the DistanceToNextPoint variable from the current agent with the direction based on an enum called DirectionPriority.
      • Returns UpdateStatus.Success when the agent has reached the destination, otherwise, returns UpdateStatus.Running.
    • Patrol: Patrols around the waypoints.
      • It will move to the next way point in the Waypoints variable if it has reached the current one.
      • Always returns UpdateStatus.Running.
  • FaceTarget: Faces the target.
    • Returns UpdateStatus.Success right after the first update.
  • FaceTargetForever. Faces the target forever.
    • Always returns UpdateStatus.Running.

Properties and Functions

Properties

Here are some useful properties that you can use in your defined tasks:

Transform Transform { get; private set; }  

GameObject GameObject { get; private set; }  

UtilityAgentController AgentController { get; private set; }

Functions

GetComponent Functions

You can get any component attached to the GameObject by calling these functions:

T GetComponent<T>()
T GetComponentInChildren<T>()

Coroutine functions

We provides these functions to help you start/stop coroutines from action tasks:

void StartCoroutine(string methodName);

Coroutine StartCoroutine(IEnumerator routine);

Coroutine StartCoroutine(string methodName, object value);

void StopCoroutine(string methodName);

void StopCoroutine(IEnumerator routine);

void StopAllCoroutines();

Overridable Functions

Here is the list of functions you could override to make your actions works as you want:

  • Lifecycle Functions:

    void OnAwake();
    
    void OnStart();
    
    Status OnUpdate();
    
    void OnLateUpdate();
    
    void OnFixedUpdate();
    
    //OnAbort is called when the action's target changes or when the agent makes a new decision
    void OnAbort();
    
    //OnEnd is called after the action returns a success or failure
    void OnEnd();
    

  • Collision/Trigger 3D:

    void OnCollisionEnter(Collision collision);
    
    void OnCollisionStay(Collision collision);
    
    void OnCollisionExit(Collision collision);
    
    void OnTriggerEnter(Collider other);
    
    void OnTriggerStay(Collider other);
    
    void OnTriggerExit(Collider other);
    
    void OnControllerColliderHit(ControllerColliderHit hit);
    

  • Collision/Trigger 2D:

    void OnCollisionEnter2D(Collision2D collision);
    
    void OnCollisionStay2D(Collision2D collision);
    
    void OnCollisionExit2D(Collision2D collision);
    
    void OnTriggerEnter2D(Collider2D other);
    
    void OnTriggerStay2D(Collider2D other);
    
    void OnTriggerExit2D(Collider2D other);
    

  • Animation:

    void OnAnimatorMove();
    
    void OnAnimatorIK(int layerIndex);
    


If you haven’t already, please consider leaving a review on the Asset Store. Whether good or bad, your feedback helps shape the future of this framework, and lets others determine whether it’s a good fit for their games. Thank you so much!💘 I love you all!🥰


Last update : September 29, 2025
Created : September 1, 2024