From 97da432c35b8c7aaf9dd2c39e2aa4b1f55f36065 Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 27 Jan 2021 16:15:06 +0800 Subject: +behaviour designer --- .../Runtime/Composites/SelectorEvaluator.cs | 120 +++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 Client/Assets/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs (limited to 'Client/Assets/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs') diff --git a/Client/Assets/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs b/Client/Assets/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs new file mode 100644 index 00000000..08bd350c --- /dev/null +++ b/Client/Assets/Behavior Designer/Runtime/Composites/SelectorEvaluator.cs @@ -0,0 +1,120 @@ +using UnityEngine; + +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 -- cgit v1.1-26-g67d0