Implementing behavior trees

Behavior trees can be seen as a synthesis of a number of other artificial intelligence techniques, such as finite-state machines, planning, and decision trees. In fact, they share some resemblance to FSMs, but instead of states, we think in terms of actions spanned across a tree structure.

Getting ready

This recipe requires us to understand Coroutines.

How to do it...

Just like decisions trees, we will create three pseudo-abstract classes for handling the process:

  1. Create the base class, Task:
    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    
    public class Task : MonoBehaviour
    {
        public List<Task> children;
        protected bool result = false;
        protected bool isFinished = false;
    }
  2. Implement the finalization function:
    public virtual void SetResult(bool r)
    {
        result = r;
        isFinished = true;
    }
  3. Implement the function for creating behaviors:
    public virtual IEnumerator Run()
    {
        SetResult(true);
        yield break;
    }
  4. Implement the general function for starting behaviors:
    public virtual IEnumerator RunTask()
    {
        yield return StartCoroutine(Run());
    }
  5. Create the ConditionBT class:
    using UnityEngine;
    using System.Collections;
    
    public class ConditionBT : Task
    {
        public override IEnumerator Run()
        {
            isFinished = false;
            bool r = false;
            // implement your behaviour here
            // define result (r) whether true or false
            //---------
            SetResult(r);
            yield break;
        }
    }
  6. Create the base class for actions:
    using UnityEngine;
    using System.Collections;
    
    public class ActionBT : Task
    {
        public override IEnumerator Run()
        {
            isFinished = false;
            // implement your behaviour here
            //---------
            return base.Run();
        }
    }
  7. Implement the Selector class:
    using UnityEngine;
    using System.Collections;
    
    public class Selector : Task
    {
        public override void SetResult(bool r)
        {
            if (r == true)
                isFinished = true;
        }
    
        public override IEnumerator RunTask()
        {
            foreach (Task t in children)
                yield return StartCoroutine(t.RunTask());
        }
    }
  8. Implement also the Sequence class:
    using UnityEngine;
    using System.Collections;
    
    public class Sequence : Task
    {
        public override void SetResult(bool r)
        {
            if (r == true)
                isFinished = true;
        }
    
        public override IEnumerator RunTask()
        {
            foreach (Task t in children)
                yield return StartCoroutine(t.RunTask());
        }
    }

How it works...

Behavior trees work in a similar fashion to decision trees. However, the leaf nodes are called tasks and there are some branch nodes that are not conditions, but run a set of tasks in one of two ways; Selector and Sequence. Selectors run a set of tasks and return true when one of their tasks return true, it can be seen as an OR node. Sequences run a set of tasks and return true when all of their tasks return true, it can be seen as an AND node.

See also

For more theoretical insights, refer to Ian Millington's book, Artificial Intelligence for Games.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.142.194