summaryrefslogtreecommitdiff
path: root/Client/Assets/Behavior Designer/Runtime/Composites/RandomSequence.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Client/Assets/Behavior Designer/Runtime/Composites/RandomSequence.cs')
-rw-r--r--Client/Assets/Behavior Designer/Runtime/Composites/RandomSequence.cs103
1 files changed, 103 insertions, 0 deletions
diff --git a/Client/Assets/Behavior Designer/Runtime/Composites/RandomSequence.cs b/Client/Assets/Behavior Designer/Runtime/Composites/RandomSequence.cs
new file mode 100644
index 00000000..0d4e2223
--- /dev/null
+++ b/Client/Assets/Behavior Designer/Runtime/Composites/RandomSequence.cs
@@ -0,0 +1,103 @@
+using UnityEngine;
+using System.Collections.Generic;
+
+namespace BehaviorDesigner.Runtime.Tasks
+{
+ [TaskDescription("Similar to the sequence task, the random sequence task will return success as soon as every child task returns success. " +
+ "The difference is that the random sequence class will run its children in a random order. The sequence task is deterministic " +
+ "in that it will always run the tasks from left to right within the tree. The random sequence task shuffles the child tasks up and then begins " +
+ "execution in a random order. Other than that the random sequence class is the same as the sequence class. It will stop running tasks " +
+ "as soon as a single task ends in failure. On a task failure it will stop executing all of the child tasks and return failure. " +
+ "If no child returns failure then it will return success.")]
+ [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=31")]
+ [TaskIcon("{SkinColor}RandomSequenceIcon.png")]
+ public class RandomSequence : Composite
+ {
+ [Tooltip("Seed the random number generator to make things easier to debug")]
+ public int seed = 0;
+ [Tooltip("Do we want to use the seed?")]
+ public bool useSeed = false;
+
+ // A list of indexes of every child task. This list is used by the Fischer-Yates shuffle algorithm.
+ private List<int> childIndexList = new List<int>();
+ // The random child index execution order.
+ private Stack<int> childrenExecutionOrder = new Stack<int>();
+ // The task status of the last child ran.
+ private TaskStatus executionStatus = TaskStatus.Inactive;
+
+ public override void OnAwake()
+ {
+ // If specified, use the seed provided.
+ if (useSeed) {
+ Random.InitState(seed);
+ }
+
+ // Add the index of each child to a list to make the Fischer-Yates shuffle possible.
+ childIndexList.Clear();
+ for (int i = 0; i < children.Count; ++i) {
+ childIndexList.Add(i);
+ }
+ }
+
+ public override void OnStart()
+ {
+ // Randomize the indecies
+ ShuffleChilden();
+ }
+
+ public override int CurrentChildIndex()
+ {
+ // Peek will return the index at the top of the stack.
+ return childrenExecutionOrder.Peek();
+ }
+
+ public override bool CanExecute()
+ {
+ // Continue exectuion if no task has return failure and indexes still exist on the stack.
+ return childrenExecutionOrder.Count > 0 && executionStatus != TaskStatus.Failure;
+ }
+
+ public override void OnChildExecuted(TaskStatus childStatus)
+ {
+ // Pop the top index from the stack and set the execution status.
+ if (childrenExecutionOrder.Count > 0) {
+ childrenExecutionOrder.Pop();
+ }
+ executionStatus = childStatus;
+ }
+
+ public override void OnConditionalAbort(int childIndex)
+ {
+ // Start from the beginning on an abort
+ childrenExecutionOrder.Clear();
+ executionStatus = TaskStatus.Inactive;
+ ShuffleChilden();
+ }
+
+ public override void OnEnd()
+ {
+ // All of the children have run. Reset the variables back to their starting values.
+ executionStatus = TaskStatus.Inactive;
+ childrenExecutionOrder.Clear();
+ }
+
+ public override void OnReset()
+ {
+ // Reset the public properties back to their original values
+ seed = 0;
+ useSeed = false;
+ }
+
+ private void ShuffleChilden()
+ {
+ // Use Fischer-Yates shuffle to randomize the child index order.
+ for (int i = childIndexList.Count; i > 0; --i) {
+ int j = Random.Range(0, i);
+ int index = childIndexList[j];
+ childrenExecutionOrder.Push(index);
+ childIndexList[j] = childIndexList[i - 1];
+ childIndexList[i - 1] = index;
+ }
+ }
+ }
+} \ No newline at end of file