ℹ️ Select 'Choose Exercise', or randomize 'Next Random Exercise' in selected language.

Choose Exercise:
Timer 00:00
WPM --
Score --
Acc --
Correct chars --

AI Behavior Tree Node - Sequence Execution

C# (Unity)

Goal -- WPM

Ready
Exercise Algorithm Area
1using System.Collections.Generic;
2using UnityEngine;
3
4public enum BehaviorTreeStatus
5{
6Success,
7Failure,
8Running
9}
10
11public abstract class BehaviorTreeNode
12{
13public abstract BehaviorTreeStatus Tick(GameObject agent);
14}
15
16public class SequenceNode : BehaviorTreeNode
17{
18private List<BehaviorTreeNode> children = new List<BehaviorTreeNode>();
19private int currentChildIndex = 0;
20
21public void AddChild(BehaviorTreeNode child)
22{
23if (child != null)
24{
25children.Add(child);
26}
27}
28
29public override BehaviorTreeStatus Tick(GameObject agent)
30{
31if (children.Count == 0)
32{
33return BehaviorTreeStatus.Success; // An empty sequence succeeds vacuously
34}
35
36// Iterate through children, starting from where we left off last tick
37for (int i = currentChildIndex; i < children.Count; i++)
38{
39BehaviorTreeNode child = children[i];
40BehaviorTreeStatus childStatus = child.Tick(agent);
41
42if (childStatus == BehaviorTreeStatus.Failure)
43{
44// If any child fails, the sequence fails immediately.
45// Reset index for next time.
46currentChildIndex = 0;
47return BehaviorTreeStatus.Failure;
48}
49else if (childStatus == BehaviorTreeStatus.Running)
50{
51// If any child is running, the sequence is also running.
52// Store the index of the running child so we can resume from it.
53currentChildIndex = i;
54return BehaviorTreeStatus.Running;
55}
56// If childStatus is Success, continue to the next child
57}
58
59// If all children succeeded, the sequence succeeds.
60// Reset index for the next tick.
61currentChildIndex = 0;
62return BehaviorTreeStatus.Success;
63}
64}
65
66// Example Child Nodes (for demonstration)
67public class SuccessNode : BehaviorTreeNode
68{
69public override BehaviorTreeStatus Tick(GameObject agent)
70{
71Debug.Log("SuccessNode Ticked: Success");
72return BehaviorTreeStatus.Success;
73}
74}
75
76public class FailureNode : BehaviorTreeNode
77{
78public override BehaviorTreeStatus Tick(GameObject agent)
79{
80Debug.Log("FailureNode Ticked: Failure");
81return BehaviorTreeStatus.Failure;
82}
83}
84
85public class RunningNode : BehaviorTreeNode
86{
87private int ticksToRun;
88private int currentTick = 0;
89
90public RunningNode(int ticks)
91{
92ticksToRun = ticks;
93}
94
95public override BehaviorTreeStatus Tick(GameObject agent)
96{
97if (currentTick < ticksToRun)
98{
99Debug.Log($"RunningNode Ticked: Running (Tick {currentTick + 1}/{ticksToRun})");
100currentTick++;
101return BehaviorTreeStatus.Running;
102}
103else
104{
105Debug.Log("RunningNode Ticked: Success (finished running)");
106currentTick = 0; // Reset for next time
107return BehaviorTreeStatus.Success;
108}
109}
110}
111
112// Example Usage (would typically be part of a larger Behavior Tree system)
113public class BehaviorTreeExample : MonoBehaviour
114{
115void Start()
116{
117// Example 1: All children succeed
118Debug.Log("--- Example 1: All Success ---");
119var sequence1 = new SequenceNode();
120sequence1.AddChild(new SuccessNode());
121sequence1.AddChild(new SuccessNode());
122sequence1.Tick(gameObject);
123
124// Example 2: First child fails
125Debug.Log("\n--- Example 2: First Child Fails ---");
126var sequence2 = new SequenceNode();
127sequence2.AddChild(new FailureNode());
128sequence2.AddChild(new SuccessNode());
129sequence2.Tick(gameObject);
130
131// Example 3: Middle child fails
132Debug.Log("\n--- Example 3: Middle Child Fails ---");
133var sequence3 = new SequenceNode();
134sequence3.AddChild(new SuccessNode());
135sequence3.AddChild(new FailureNode());
136sequence3.AddChild(new SuccessNode());
137sequence3.Tick(gameObject);
138
139// Example 4: Child returns Running
140Debug.Log("\n--- Example 4: Child Returns Running ---");
141var sequence4 = new SequenceNode();
142sequence4.AddChild(new SuccessNode());
143sequence4.AddChild(new RunningNode(2)); // This node will run for 2 ticks
144sequence4.AddChild(new SuccessNode());
145
146Debug.Log("Tick 1:");
147sequence4.Tick(gameObject);
148Debug.Log("Tick 2:");
149sequence4.Tick(gameObject);
150Debug.Log("Tick 3:");
151sequence4.Tick(gameObject);
152
153// Example 5: Empty sequence
154Debug.Log("\n--- Example 5: Empty Sequence ---");
155var sequence5 = new SequenceNode();
156sequence5.Tick(gameObject);
157}
158}
Algorithm description viewbox

AI Behavior Tree Node - Sequence Execution

Algorithm description:

This C# code implements a `SequenceNode` for AI Behavior Trees, a hierarchical structure used to define complex AI decision-making. The `SequenceNode` executes its child nodes sequentially, succeeding only if all children succeed. If any child fails or returns `Running`, the `SequenceNode` immediately returns that status, pausing its execution until the next tick. This pattern is fundamental for creating ordered actions and conditional logic in AI.

Algorithm explanation:

The `SequenceNode`'s `Tick` method iterates through its children. It maintains `currentChildIndex` to resume execution from the last point if a child returned `Running`. If a child returns `Failure`, the `SequenceNode` immediately returns `Failure` and resets `currentChildIndex`. If a child returns `Running`, the `SequenceNode` stores the current child's index and returns `Running`. Only if a child returns `Success` does the `SequenceNode` proceed to the next child. If all children are successfully executed, the `SequenceNode` returns `Success` and resets `currentChildIndex`. The time complexity of a `Tick` operation for a `SequenceNode` is O(N) in the worst case, where N is the number of children, as it might need to tick all of them if they all succeed. In cases where a child fails or returns running early, it can be O(1) or O(k) where k is the index of the failing/running child. Space complexity is O(N) to store the children. Edge cases include an empty sequence (which succeeds vacuously) and resuming execution from a `Running` child.

Pseudocode:

Enum BehaviorTreeStatus { Success, Failure, Running }

Abstract Class BehaviorTreeNode:
  Abstract Method Tick(agent):
    Returns BehaviorTreeStatus

Class SequenceNode (inherits BehaviorTreeNode):
  Children list (BehaviorTreeNode)
  CurrentChildIndex (int)

  Method AddChild(child):
    Add child to Children list

  Method Tick(agent):
    If Children list is empty, return Success

    Loop from currentChildIndex to end of Children list:
      child = Children[loop index]
      childStatus = child.Tick(agent)

      If childStatus is Failure:
        currentChildIndex = 0
        Return Failure
      Else if childStatus is Running:
        currentChildIndex = loop index
        Return Running
      // If childStatus is Success, continue loop

    // If loop completes, all children succeeded
    currentChildIndex = 0
    Return Success