From 21e186f75b504d832d9c7bef0456edd7d5d3155e Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 8 Sep 2021 10:52:35 +0800 Subject: +behavior design --- .../Runtime/Composites/Parallel.cs | 87 ++++++++++++ .../Runtime/Composites/Parallel.cs.meta | 7 + .../Runtime/Composites/ParallelComplete.cs | 81 +++++++++++ .../Runtime/Composites/ParallelComplete.cs.meta | 12 ++ .../Runtime/Composites/ParallelSelector.cs | 87 ++++++++++++ .../Runtime/Composites/ParallelSelector.cs.meta | 7 + .../Runtime/Composites/PrioritySelector.cs | 72 ++++++++++ .../Runtime/Composites/PrioritySelector.cs.meta | 7 + .../Runtime/Composites/RandomSelector.cs | 106 +++++++++++++++ .../Runtime/Composites/RandomSelector.cs.meta | 7 + .../Runtime/Composites/RandomSequence.cs | 107 +++++++++++++++ .../Runtime/Composites/RandomSequence.cs.meta | 7 + .../Runtime/Composites/Selector.cs | 46 +++++++ .../Runtime/Composites/Selector.cs.meta | 7 + .../Runtime/Composites/SelectorEvaluator.cs | 118 ++++++++++++++++ .../Runtime/Composites/SelectorEvaluator.cs.meta | 8 ++ .../Runtime/Composites/Sequence.cs | 46 +++++++ .../Runtime/Composites/Sequence.cs.meta | 7 + .../Runtime/Composites/UtilitySelector.cs | 150 +++++++++++++++++++++ .../Runtime/Composites/UtilitySelector.cs.meta | 12 ++ 20 files changed, 981 insertions(+) create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs.meta create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs create mode 100644 Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs.meta (limited to 'Assets/ThirdParty/Behavior Designer/Runtime/Composites') diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs new file mode 100644 index 00000000..79969d26 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs @@ -0,0 +1,87 @@ +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("Similar to the sequence task, the parallel task will run each child task until a child task returns failure. " + + "The difference is that the parallel task will run all of its children tasks simultaneously versus running each task one at a time. " + + "Like the sequence class, the parallel task will return success once all of its children tasks have return success. " + + "If one tasks returns failure the parallel task will end all of the child tasks and return failure.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=27")] + [TaskIcon("{SkinColor}ParallelIcon.png")] + public class Parallel : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex; + // The task status of every child task. + private TaskStatus[] executionStatus; + + public override void OnAwake() + { + // Create a new task status array that will hold the execution status of all of the children tasks. + executionStatus = new TaskStatus[children.Count]; + } + + public override void OnChildStarted(int childIndex) + { + // One of the children has started to run. Increment the child index and set the current task status of that child to running. + currentChildIndex++; + executionStatus[childIndex] = TaskStatus.Running; + } + + public override bool CanRunParallelChildren() + { + // This task can run parallel children. + return true; + } + + public override int CurrentChildIndex() + { + return currentChildIndex; + } + + public override bool CanExecute() + { + // We can continue executing if we have more children that haven't been started yet. + return currentChildIndex < children.Count; + } + + public override void OnChildExecuted(int childIndex, TaskStatus childStatus) + { + // One of the children has finished running. Set the task status. + executionStatus[childIndex] = childStatus; + } + + public override TaskStatus OverrideStatus(TaskStatus status) + { + // Assume all of the children have finished executing. Loop through the execution status of every child and check to see if any tasks are currently running + // or failed. If a task is still running then all of the children are not done executing and the parallel task should continue to return a task status of running. + // If a task failed then return failure. The Behavior Manager will stop all of the children tasks. If no child task is running or has failed then the parallel + // task succeeded and it will return success. + bool childrenComplete = true; + for (int i = 0; i < executionStatus.Length; ++i) { + if (executionStatus[i] == TaskStatus.Running) { + childrenComplete = false; + } else if (executionStatus[i] == TaskStatus.Failure) { + return TaskStatus.Failure; + } + } + return (childrenComplete ? TaskStatus.Success : TaskStatus.Running); + } + + public override void OnConditionalAbort(int childIndex) + { + // Start from the beginning on an abort + currentChildIndex = 0; + for (int i = 0; i < executionStatus.Length; ++i) { + executionStatus[i] = TaskStatus.Inactive; + } + } + + public override void OnEnd() + { + // Reset the execution status and the child index back to their starting values. + for (int i = 0; i < executionStatus.Length; ++i) { + executionStatus[i] = TaskStatus.Inactive; + } + currentChildIndex = 0; + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs.meta new file mode 100644 index 00000000..4d4def85 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Parallel.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4a7063721a0dbc04787bec1b0507f9ae +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs new file mode 100644 index 00000000..cfbab87a --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs @@ -0,0 +1,81 @@ +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("Similar to the parallel selector task, except the parallel complete task will return the child status as soon as the child returns success or failure." + + "The child tasks are executed simultaneously.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=136")] + [TaskIcon("{SkinColor}ParallelCompleteIcon.png")] + public class ParallelComplete : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex; + // The task status of every child task. + private TaskStatus[] executionStatus; + + public override void OnAwake() + { + // Create a new task status array that will hold the execution status of all of the children tasks. + executionStatus = new TaskStatus[children.Count]; + } + + public override void OnChildStarted(int childIndex) + { + // One of the children has started to run. Increment the child index and set the current task status of that child to running. + currentChildIndex++; + executionStatus[childIndex] = TaskStatus.Running; + } + + public override bool CanRunParallelChildren() + { + // This task can run parallel children. + return true; + } + + public override int CurrentChildIndex() + { + return currentChildIndex; + } + + public override bool CanExecute() + { + // We can continue executing if we have more children that haven't been started yet. + return currentChildIndex < children.Count; + } + + public override void OnChildExecuted(int childIndex, TaskStatus childStatus) + { + // One of the children has finished running. Set the task status. + executionStatus[childIndex] = childStatus; + } + + public override void OnConditionalAbort(int childIndex) + { + // Start from the beginning on an abort + currentChildIndex = 0; + for (int i = 0; i < executionStatus.Length; ++i) { + executionStatus[i] = TaskStatus.Inactive; + } + } + + public override TaskStatus OverrideStatus(TaskStatus status) + { + // Return the child task's status as soon as a child task returns success or failure. + for (int i = 0; i < executionStatus.Length; ++i) { + if (executionStatus[i] == TaskStatus.Success || executionStatus[i] == TaskStatus.Failure) { + return executionStatus[i]; + } else if (executionStatus[i] == TaskStatus.Inactive) { + return TaskStatus.Success; + } + } + return TaskStatus.Running; + } + + public override void OnEnd() + { + // Reset the execution status and the child index back to their starting values. + for (int i = 0; i < executionStatus.Length; ++i) { + executionStatus[i] = TaskStatus.Inactive; + } + currentChildIndex = 0; + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs.meta new file mode 100644 index 00000000..fc7dd0a8 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelComplete.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ef4b3eb51f6ede04bba3598677fe8531 +timeCreated: 1487379311 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs new file mode 100644 index 00000000..13e6624a --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs @@ -0,0 +1,87 @@ +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("Similar to the selector task, the parallel selector task will return success as soon as a child task returns success. " + + "The difference is that the parallel task will run all of its children tasks simultaneously versus running each task one at a time. " + + "If one tasks returns success the parallel selector task will end all of the child tasks and return success. " + + "If every child task returns failure then the parallel selector task will return failure.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=28")] + [TaskIcon("{SkinColor}ParallelSelectorIcon.png")] + public class ParallelSelector : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex; + // The task status of every child task. + private TaskStatus[] executionStatus; + + public override void OnAwake() + { + // Create a new task status array that will hold the execution status of all of the children tasks. + executionStatus = new TaskStatus[children.Count]; + } + + public override void OnChildStarted(int childIndex) + { + // One of the children has started to run. Increment the child index and set the current task status of that child to running. + currentChildIndex++; + executionStatus[childIndex] = TaskStatus.Running; + } + + public override bool CanRunParallelChildren() + { + // This task can run parallel children. + return true; + } + + public override int CurrentChildIndex() + { + return currentChildIndex; + } + + public override bool CanExecute() + { + // We can continue executing if we have more children that haven't been started yet. + return currentChildIndex < children.Count; + } + + public override void OnChildExecuted(int childIndex, TaskStatus childStatus) + { + // One of the children has finished running. Set the task status. + executionStatus[childIndex] = childStatus; + } + + public override void OnConditionalAbort(int childIndex) + { + // Start from the beginning on an abort + currentChildIndex = 0; + for (int i = 0; i < executionStatus.Length; ++i) { + executionStatus[i] = TaskStatus.Inactive; + } + } + + public override TaskStatus OverrideStatus(TaskStatus status) + { + // Assume all of the children have finished executing. Loop through the execution status of every child and check to see if any tasks are currently running + // or succeeded. If a task is still running then all of the children are not done executing and the parallel selector task should continue to return a task status of running. + // If a task succeeded then return success. The Behavior Manager will stop all of the children tasks. If no child task is running or has succeeded then the parallel selector + // task failed and it will return failure. + bool childrenComplete = true; + for (int i = 0; i < executionStatus.Length; ++i) { + if (executionStatus[i] == TaskStatus.Running) { + childrenComplete = false; + } else if (executionStatus[i] == TaskStatus.Success) { + return TaskStatus.Success; + } + } + return (childrenComplete ? TaskStatus.Failure : TaskStatus.Running); + } + + public override void OnEnd() + { + // Reset the execution status and the child index back to their starting values. + for (int i = 0; i < executionStatus.Length; ++i) { + executionStatus[i] = TaskStatus.Inactive; + } + currentChildIndex = 0; + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs.meta new file mode 100644 index 00000000..dde9d512 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/ParallelSelector.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 52e4e27ad95cedb41a3bc2c5f5ed0b54 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs new file mode 100644 index 00000000..5f2dac27 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs @@ -0,0 +1,72 @@ +using System.Collections.Generic; + +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("Similar to the selector task, the priority selector task will return success as soon as a child task returns success. " + + "Instead of running the tasks sequentially from left to right within the tree, the priority selector will ask the task what its priority is to determine the order. " + + "The higher priority tasks have a higher chance at being run first.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=29")] + [TaskIcon("{SkinColor}PrioritySelectorIcon.png")] + public class PrioritySelector : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex = 0; + // The task status of every child task. + private TaskStatus executionStatus = TaskStatus.Inactive; + // The order to run its children in. + private List childrenExecutionOrder = new List(); + + public override void OnStart() + { + // Make sure the list is empty before we add child indexes to it. + childrenExecutionOrder.Clear(); + + // Loop through each child task and determine its priority. The higher the priority the lower it goes within the list. The task with the highest + // priority will be first in the list and will be executed first. + for (int i = 0; i < children.Count; ++i) { + float priority = children[i].GetPriority(); + int insertIndex = childrenExecutionOrder.Count; + for (int j = 0; j < childrenExecutionOrder.Count; ++j) { + if (children[childrenExecutionOrder[j]].GetPriority() < priority) { + insertIndex = j; + break; + } + } + childrenExecutionOrder.Insert(insertIndex, i); + } + } + + public override int CurrentChildIndex() + { + // Use the execution order list in order to determine the current child index. + return childrenExecutionOrder[currentChildIndex]; + } + + public override bool CanExecute() + { + // We can continue to execuate as long as we have children that haven't been executed and no child has returned success. + return currentChildIndex < children.Count && executionStatus != TaskStatus.Success; + } + + public override void OnChildExecuted(TaskStatus childStatus) + { + // Increase the child index and update the execution status after a child has finished running. + currentChildIndex++; + executionStatus = childStatus; + } + + public override void OnConditionalAbort(int childIndex) + { + // Set the current child index to the index that caused the abort + currentChildIndex = childIndex; + executionStatus = TaskStatus.Inactive; + } + + public override void OnEnd() + { + // All of the children have run. Reset the variables back to their starting values. + executionStatus = TaskStatus.Inactive; + currentChildIndex = 0; + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs.meta new file mode 100644 index 00000000..828e4c7a --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/PrioritySelector.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8b5aa86ad86e94f41841abd04bd96f2a +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs new file mode 100644 index 00000000..e4c55f0f --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs @@ -0,0 +1,106 @@ +using UnityEngine; +using System.Collections.Generic; + +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("Similar to the selector task, the random selector task will return success as soon as a child task returns success. " + + "The difference is that the random selector class will run its children in a random order. The selector task is deterministic " + + "in that it will always run the tasks from left to right within the tree. The random selector task shuffles the child tasks up and then begins " + + "execution in a random order. Other than that the random selector class is the same as the selector class. It will continue running tasks " + + "until a task completes successfully. If no child tasks return success then it will return failure.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=30")] + [TaskIcon("{SkinColor}RandomSelectorIcon.png")] + public class RandomSelector : 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 childIndexList = new List(); + // The random child index execution order. + private Stack childrenExecutionOrder = new Stack(); + // 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) { +#if !(UNITY_5_1 || UNITY_5_2 || UNITY_5_3) + Random.InitState(seed); +#else + Random.seed = seed; +#endif + } + + // 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 success and indexes still exist on the stack. + return childrenExecutionOrder.Count > 0 && executionStatus != TaskStatus.Success; + } + + 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 diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs.meta new file mode 100644 index 00000000..d5528712 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSelector.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4952cbfc1e77be24b99e34c9acffc2a0 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs new file mode 100644 index 00000000..a392c7b1 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs @@ -0,0 +1,107 @@ +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 childIndexList = new List(); + // The random child index execution order. + private Stack childrenExecutionOrder = new Stack(); + // 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) { +#if !(UNITY_5_1 || UNITY_5_2 || UNITY_5_3) + Random.InitState(seed); +#else + Random.seed = seed; +#endif + } + + // 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 diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs.meta new file mode 100644 index 00000000..28baf39d --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/RandomSequence.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 11b102c97eb687b4a9ce1473a334c3dd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs new file mode 100644 index 00000000..e85b1ca5 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs @@ -0,0 +1,46 @@ +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("The selector task is similar to an \"or\" operation. It will return success as soon as one of its child tasks return success. " + + "If a child task returns failure then it will sequentially run the next task. If no child task returns success then it will return failure.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=26")] + [TaskIcon("{SkinColor}SelectorIcon.png")] + public class Selector : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex = 0; + // The task status of the last child ran. + private TaskStatus executionStatus = TaskStatus.Inactive; + + public override int CurrentChildIndex() + { + return currentChildIndex; + } + + public override bool CanExecute() + { + // We can continue to execuate as long as we have children that haven't been executed and no child has returned success. + return currentChildIndex < children.Count && executionStatus != TaskStatus.Success; + } + + public override void OnChildExecuted(TaskStatus childStatus) + { + // Increase the child index and update the execution status after a child has finished running. + currentChildIndex++; + executionStatus = childStatus; + } + + public override void OnConditionalAbort(int childIndex) + { + // Set the current child index to the index that caused the abort + currentChildIndex = childIndex; + executionStatus = TaskStatus.Inactive; + } + + public override void OnEnd() + { + // All of the children have run. Reset the variables back to their starting values. + executionStatus = TaskStatus.Inactive; + currentChildIndex = 0; + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs.meta new file mode 100644 index 00000000..a3f6291c --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Selector.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7cb8dcec14880a443841212e6b595d4f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs new file mode 100644 index 00000000..25505d63 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs @@ -0,0 +1,118 @@ +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("The selector evaluator is a selector task which reevaluates its children every tick. It will run the lowest priority child which returns a task status of running. " + + "This is done each tick. If a higher priority child is running and the next frame a lower priority child wants to run it will interrupt the higher priority child. " + + "The selector evaluator will return success as soon as the first child returns success otherwise it will keep trying higher priority children. This task mimics " + + "the conditional abort functionality except the child tasks don't always have to be conditional tasks.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=109")] + [TaskIcon("{SkinColor}SelectorEvaluatorIcon.png")] + public class SelectorEvaluator : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex = 0; + // The task status of the last child ran. + private TaskStatus executionStatus = TaskStatus.Inactive; + // The index of the child that was running before the tree started to be reevaluated. + private int storedCurrentChildIndex = -1; + // The task status of the last child ran before the tree started to be reevaluated. + private TaskStatus storedExecutionStatus = TaskStatus.Inactive; + + public override int CurrentChildIndex() + { + return currentChildIndex; + } + + public override void OnChildStarted(int childIndex) + { + // The children run sequentially so increment the index and set the status to running. + currentChildIndex++; + executionStatus = TaskStatus.Running; + } + + public override bool CanExecute() + { + // We can continue to execuate as long as we have children that haven't been executed and no child has returned success. + if (executionStatus == TaskStatus.Success || executionStatus == TaskStatus.Running) { + return false; + } + + // Used the storedCurrentChildIndex if reevaluating, otherwise the currentChildIndex + if (storedCurrentChildIndex != -1) { + return currentChildIndex < storedCurrentChildIndex - 1; + } + return currentChildIndex < children.Count; + } + + public override void OnChildExecuted(int childIndex, TaskStatus childStatus) + { + // The child status will be inactive immediately following an abort from OnReevaluationEnded. The status will be running if the + // child task is interrupted. Ignore the status for both of these. + if (childStatus != TaskStatus.Inactive && childStatus != TaskStatus.Running) { + executionStatus = childStatus; + } + } + + public override void OnConditionalAbort(int childIndex) + { + // Set the current child index to the index that caused the abort + currentChildIndex = childIndex; + executionStatus = TaskStatus.Inactive; + } + + public override void OnEnd() + { + // All of the children have run. Reset the variables back to their starting values. + executionStatus = TaskStatus.Inactive; + currentChildIndex = 0; + } + + public override TaskStatus OverrideStatus(TaskStatus status) + { + return executionStatus; + } + + // The selector evaluator task is a parallel task to allow the previous child to continue to run while the higher priority task is active. If the + // lower priority child can run then OnReevaluationEnded will interrupt the higher priority task. + public override bool CanRunParallelChildren() + { + return true; + } + + // Can reevaluate to allow the lower priority children the chance to rerun. + public override bool CanReevaluate() + { + return true; + } + + // The behavior tree wants to start reevaluating the tree. + public override bool OnReevaluationStarted() + { + // Cannot reevaluate if the task hasn't even started yet + if (executionStatus == TaskStatus.Inactive) { + return false; + } + + // Store the current index and execution status because it may need to be resumed. + storedCurrentChildIndex = currentChildIndex; + storedExecutionStatus = executionStatus; + currentChildIndex = 0; + executionStatus = TaskStatus.Inactive; + return true; + } + + // Reevaluation has ended. Determine if a task should be interrupted or resumed from the last index. + public override void OnReevaluationEnded(TaskStatus status) + { + // Interrupt the currently running index if a lower priority child returns a status of running or success. + if (executionStatus != TaskStatus.Failure && executionStatus != TaskStatus.Inactive) { + BehaviorManager.instance.Interrupt(Owner, children[storedCurrentChildIndex - 1], this); + } else { + // The lower priority children returned the same status so resume with the current child + currentChildIndex = storedCurrentChildIndex; + executionStatus = storedExecutionStatus; + } + storedCurrentChildIndex = -1; + storedExecutionStatus = TaskStatus.Inactive; + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs.meta new file mode 100644 index 00000000..b55971ba --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 15b5d0aafd7d4f04f8332d33705ebd63 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs new file mode 100644 index 00000000..c82ce730 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs @@ -0,0 +1,46 @@ +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("The sequence task is similar to an \"and\" operation. It will return failure as soon as one of its child tasks return failure. " + + "If a child task returns success then it will sequentially run the next task. If all child tasks return success then it will return success.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=25")] + [TaskIcon("{SkinColor}SequenceIcon.png")] + public class Sequence : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex = 0; + // The task status of the last child ran. + private TaskStatus executionStatus = TaskStatus.Inactive; + + public override int CurrentChildIndex() + { + return currentChildIndex; + } + + public override bool CanExecute() + { + // We can continue to execuate as long as we have children that haven't been executed and no child has returned failure. + return currentChildIndex < children.Count && executionStatus != TaskStatus.Failure; + } + + public override void OnChildExecuted(TaskStatus childStatus) + { + // Increase the child index and update the execution status after a child has finished running. + currentChildIndex++; + executionStatus = childStatus; + } + + public override void OnConditionalAbort(int childIndex) + { + // Set the current child index to the index that caused the abort + currentChildIndex = childIndex; + executionStatus = TaskStatus.Inactive; + } + + public override void OnEnd() + { + // All of the children have run. Reset the variables back to their starting values. + executionStatus = TaskStatus.Inactive; + currentChildIndex = 0; + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs.meta new file mode 100644 index 00000000..89002187 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/Sequence.cs.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b7226608b64066c40a656d7260249fce +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs new file mode 100644 index 00000000..23fd6a54 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs @@ -0,0 +1,150 @@ +using System.Collections.Generic; + +namespace BehaviorDesigner.Runtime.Tasks +{ + [TaskDescription("The utility selector task evaluates the child tasks using Utility Theory AI. The child task can override the GetUtility method and return the utility value " + + "at that particular time. The task with the highest utility value will be selected and the existing running task will be aborted. The utility selector " + + "task reevaluates its children every tick.")] + [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=134")] + [TaskIcon("{SkinColor}UtilitySelectorIcon.png")] + public class UtilitySelector : Composite + { + // The index of the child that is currently running or is about to run. + private int currentChildIndex = 0; + // The highest utility value + private float highestUtility; + // The task status of the last child ran. + private TaskStatus executionStatus = TaskStatus.Inactive; + // Is the task being reevaluated? + private bool reevaluating; + // A list of children that can execute. + private List availableChildren = new List(); + + public override void OnStart() + { + highestUtility = float.MinValue; + + // Loop through each child task and determine its utility. The task with the highest utility will run first. + availableChildren.Clear(); + for (int i = 0; i < children.Count; ++i) { + float utility = children[i].GetUtility(); + if (utility > highestUtility) { + highestUtility = utility; + currentChildIndex = i; + } + availableChildren.Add(i); + } + } + + public override int CurrentChildIndex() + { + // The currentChildIndex is the task with the highest utility. + return currentChildIndex; + } + + public override void OnChildStarted(int childIndex) + { + // The child has started - set the execution status. + executionStatus = TaskStatus.Running; + } + + public override bool CanExecute() + { + // Continue to execute new tasks until a task returns success or there are no more children left. If reevaluating then return false + // immediately because each task doesn't need to be reevaluted. + if (executionStatus == TaskStatus.Success || executionStatus == TaskStatus.Running || reevaluating) { + return false; + } + return availableChildren.Count > 0; + } + + public override void OnChildExecuted(int childIndex, TaskStatus childStatus) + { + // The child status will be inactive immediately following an abort from OnReevaluationEnded. The status will be running if the + // child task is interrupted. Ignore the status for both of these. + if (childStatus != TaskStatus.Inactive && childStatus != TaskStatus.Running) { + executionStatus = childStatus; + // If the execution status is failure then a new task needs to be selected. Remove the current task from the available children + // and select the next highest utility child. + if (executionStatus == TaskStatus.Failure) { + availableChildren.Remove(childIndex); + + highestUtility = float.MinValue; + for (int i = 0; i < availableChildren.Count; ++i) { + float utility = children[availableChildren[i]].GetUtility(); + if (utility > highestUtility) { + highestUtility = utility; + currentChildIndex = availableChildren[i]; + } + } + } + } + } + + public override void OnConditionalAbort(int childIndex) + { + // Set the current child index to the index that caused the abort + currentChildIndex = childIndex; + executionStatus = TaskStatus.Inactive; + } + + public override void OnEnd() + { + // All of the children have run. Reset the variables back to their starting values. + executionStatus = TaskStatus.Inactive; + currentChildIndex = 0; + } + + public override TaskStatus OverrideStatus(TaskStatus status) + { + return executionStatus; + } + + // The utility selector task is a parallel task to allow the task utility to be reevaluated. The higest utility task will always run. + public override bool CanRunParallelChildren() + { + return true; + } + + // Can reevaluate to allow the task utilities to be rerun. + public override bool CanReevaluate() + { + return true; + } + + // The behavior tree wants to start reevaluating the tree. + public override bool OnReevaluationStarted() + { + // Cannot reevaluate if the task hasn't even started yet + if (executionStatus == TaskStatus.Inactive) { + return false; + } + + reevaluating = true; + return true; + } + + // Determine if a task with a higher utility exists. + public override void OnReevaluationEnded(TaskStatus status) + { + reevaluating = false; + + // Loop through all of the available children and pick the task with the highest utility. + int prevChildIndex = currentChildIndex; + highestUtility = float.MinValue; + for (int i = 0; i < availableChildren.Count; ++i) { + float utility = children[availableChildren[i]].GetUtility(); + if (utility > highestUtility) { + highestUtility = utility; + currentChildIndex = availableChildren[i]; + } + } + + // If the index is different then the current child task should be aborted and the higher utility task should be run. + if (prevChildIndex != currentChildIndex) { + BehaviorManager.instance.Interrupt(Owner, children[prevChildIndex], this); + executionStatus = TaskStatus.Inactive; + } + } + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs.meta b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs.meta new file mode 100644 index 00000000..f65ef498 --- /dev/null +++ b/Assets/ThirdParty/Behavior Designer/Runtime/Composites/UtilitySelector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1c21b01ca0aa9004fa3a76c9d596eeb1 +timeCreated: 1465679373 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: -- cgit v1.1-26-g67d0