Choosing through a decision tree

One of the simplest mechanisms for tackling decision-making problems is decision trees, because they are fast and easy to grasp and implement. As a consequence, it's one of the most used techniques today; it is extensively used in other character-controlled scopes such as animations.

Getting ready

This recipe requires a good understanding of recursion and inheritance as we will constantly be implementing and calling virtual functions throughout the sections.

How to do it...

This recipe requires a lot of attention due to the number of files that we will need to handle. Overall, we will create a parent class DecisionTreeNode, from which we will derive the other ones. Finally, we will learn how to implement a couple of standard decision nodes:

  1. First, create the parent class, DecisionTreeNode:
    using UnityEngine;
    using System.Collections;
    public class DecisionTreeNode : MonoBehaviour
    {
        public virtual DecisionTreeNode MakeDecision()
        {
            return null;
        }
    }
  2. Create the pseudo-abstract class, Decision, deriving from the parent class, DecisionTreeNode:
    using UnityEngine;
    using System.Collections;
    public class Decision : DecisionTreeNode
    {
        public Action nodeTrue;
        public Action nodeFalse;
    
        public virtual Action GetBranch()
        {
            return null;
        }
    }
  3. Define the pseudo-abstract class, Action:
    using UnityEngine;
    using System.Collections;
    public class Action : DecisionTreeNode
    {
        public bool activated = false;
    
        public override DecisionTreeNode MakeDecision()
        {
            return this;
        }
    }
  4. Implement the virtual function, LateUpdate:
    public virtual void LateUpdate()
    {
        if (!activated)
            return;
        // Implement your behaviors here
    }
  5. Create the final class, DecisionTree:
    using UnityEngine;
    using System.Collections;
    public class DecisionTree : DecisionTreeNode
    {
        public DecisionTreeNode root;
        private Action actionNew;
        private Action actionOld;
    }
  6. Override the function, MakeDecision:
    public override DecisionTreeNode MakeDecision()
    {
        return root.MakeDecision();
    }
  7. Finally, implement the Update function:
    void Update()
    {
        actionNew.activated = false;
        actionOld = actionNew;
        actionNew = root.MakeDecision() as Action;
        if (actionNew == null)
            actionNew = actionOld;
        actionNew.activated = true;
    }

How it works...

Decision nodes choose which path to take, calling the MakeDecision function recursively. It is worth mentioning that branches must be decisions and leaves must be actions. Also, we should be careful not to create cycles within the tree.

How it works...

There's more...

We can create custom decisions and actions starting from the pseudo-abstract classes we already created. For example, a decision on whether to attack or run away from the player.

The custom Boolean decision:

using UnityEngine;
using System.Collections;

public class DecisionBool : Decision
{
    public bool valueDecision;
    public bool valueTest;

    public override Action GetBranch()
    {
        if (valueTest == valueDecision)
            return nodeTrue;
        return nodeFalse;
    }
}
..................Content has been hidden....................

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