美文网首页
OpenXR开发实战项目之VR BehaviorDesinger

OpenXR开发实战项目之VR BehaviorDesinger

作者: TonyWan_AR | 来源:发表于2023-12-10 16:21 被阅读0次

    一、框架视图

    二、关键代码

    myCanSeeObject

    using BehaviorDesigner.Runtime.Tasks;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using BehaviorDesigner.Runtime;
    //这个脚本是用来判断目标是否在视野内
    public class myCanSeeObject : Conditional
    {
        public Transform[] targets;
        public float filedOfViewAngle = 90;
        public float viewDistance = 7;
    
        public SharedTransform target;
    
        public override TaskStatus OnUpdate()
        {
            if (targets == null)
            {
                return TaskStatus.Failure;
            }
    
            foreach (var target in targets)
            {
                float distance = (target.position - transform.position).magnitude;
                float angle = Vector3.Angle(transform.forward, target.position - transform.position);
                if (distance < viewDistance && angle < filedOfViewAngle)
                {
                    this.target.Value = target;
                    return TaskStatus.Success;
                }
            }
            return TaskStatus.Failure;
        }
    }
    
    

    mySeek

    using BehaviorDesigner.Runtime.Tasks;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using BehaviorDesigner.Runtime;
    //这个脚本的作用就是控制游戏物体到达目标位置
    public class mySeek : Action //这个任务的调用都是由Behavior Desinger行为树去控制的
    {
        public float speed;
        public SharedTransform target; //要到达的目标位置
        public float arriveDistance = 0.1f;
        private float sqrArriveDistance;
        public override void OnStart()
        {
            sqrArriveDistance = arriveDistance * arriveDistance;
        }
        //当进入到这个任务的时候,就会调用这个方法,一直到任务结束,会进行一些位置的计算
        //这个方法的调用频率,默认是和unity里面的帧率保持一致
        public override TaskStatus OnUpdate()
        {
            //安全校验
            if(target == null || target.Value == null)
            {
                return TaskStatus.Failure;
            }
            transform.LookAt(target.Value.position);//直接朝向目标位置
            transform.position = Vector3.MoveTowards(transform.position, target.Value.position, speed*Time.deltaTime);
            if((target.Value.position - transform.position).sqrMagnitude<arriveDistance * sqrArriveDistance)
            {
                return TaskStatus.Success; //如果距离目标位置的距离比较小,认为到达了目标
            }
            return TaskStatus.Running;
    }
    }
    
    
    

    PerformInterruption

    namespace BehaviorDesigner.Runtime.Tasks
    {
        [TaskDescription("Perform the actual interruption. This will immediately stop the specified tasks from running and will return success or failure depending on the value of interrupt success.")]
        [TaskIcon("{SkinColor}PerformInterruptionIcon.png")]
        public class PerformInterruption : Action
        {
            [Tooltip("The list of tasks to interrupt. Can be any number of tasks")]
            public Interrupt[] interruptTasks;
            [Tooltip("When we interrupt the task should we return a task status of success?")]
            public SharedBool interruptSuccess;
    
            public override TaskStatus OnUpdate()
            {
                // Loop through all of the tasks and fire an interruption. Once complete return success.
                for (int i = 0; i < interruptTasks.Length; ++i) {
                    interruptTasks[i].DoInterrupt(interruptSuccess.Value ? TaskStatus.Success : TaskStatus.Failure);
                }
                return TaskStatus.Success;
            }
    
            public override void OnReset()
            {
                // Reset the properties back to their original values.
                interruptTasks = null;
                interruptSuccess = false;
            }
        }
    }
    

    RestartBehaviorTree

    using UnityEngine;
    
    namespace BehaviorDesigner.Runtime.Tasks
    {
        [TaskDescription("Restarts a behavior tree, returns success after it has been restarted.")]
        [TaskIcon("{SkinColor}RestartBehaviorTreeIcon.png")]
        public class RestartBehaviorTree : Action
        {
            [Tooltip("The GameObject of the behavior tree that should be restarted. If null use the current behavior")]
            public SharedGameObject behaviorGameObject;
            [Tooltip("The group of the behavior tree that should be restarted")]
            public SharedInt group;
    
            private Behavior behavior;
    
            public override void OnAwake()
            {
                var behaviorTrees = GetDefaultGameObject(behaviorGameObject.Value).GetComponents<Behavior>();
                if (behaviorTrees.Length == 1) {
                    behavior = behaviorTrees[0];
                } else if (behaviorTrees.Length > 1) {
                    for (int i = 0; i < behaviorTrees.Length; ++i) {
                        if (behaviorTrees[i].Group == group.Value) {
                            behavior = behaviorTrees[i];
                            break;
                        }
                    }
                    // If the group can't be found then use the first behavior tree
                    if (behavior == null) {
                        behavior = behaviorTrees[0];
                    }
                }
            }
    
            public override TaskStatus OnUpdate()
            {
                if (behavior == null) {
                    return TaskStatus.Failure;
                }
    
                // Stop the behavior tree
                behavior.DisableBehavior();
                // Start the behavior tree back up
                behavior.EnableBehavior();
                // Return success
                return TaskStatus.Success;
            }
    
            public override void OnReset()
            {
                // Reset the properties back to their original values.
                behavior = null;
            }
        }
    }
    

    StackedAction

    using UnityEngine;
    
    namespace BehaviorDesigner.Runtime.Tasks
    {
        [TaskDescription("Allows multiple action tasks to be added to a single node.")]
        [TaskIcon("{SkinColor}StackedActionIcon.png")]
        public class StackedAction : Action
        {
            [InspectTask]
            public Action[] actions;
            public enum ComparisonType
            {
                Sequence,
                Selector
            }
            [Tooltip("Specifies if the tasks should be traversed with an AND (Sequence) or an OR (Selector).")]
            public ComparisonType comparisonType;
            [Tooltip("Should the tasks be labeled within the graph?")]
            public bool graphLabel;
    
            public override void OnAwake()
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
    
                    actions[i].GameObject = gameObject;
                    actions[i].Transform = transform;
                    actions[i].Owner = Owner;
    #if UNITY_EDITOR || DLL_RELEASE || DLL_DEBUG
                    actions[i].NodeData = new NodeData();
    #endif
                    actions[i].OnAwake();
                }
            }
    
            public override void OnStart()
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnStart();
                }
            }
    
            public override TaskStatus OnUpdate()
            {
                if (actions == null) {
                    return TaskStatus.Failure;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    var executionStatus = actions[i].OnUpdate();
    #if UNITY_EDITOR || DLL_RELEASE || DLL_DEBUG
                    actions[i].NodeData.ExecutionStatus = executionStatus;
                    if (actions[i].NodeData.ExecutionStatus == TaskStatus.Running) {
                        Debug.LogWarning("Warning: The action task returned a status of running when action tasks should only return success or failure.");
                    }
    #endif
                    if (comparisonType == ComparisonType.Sequence && executionStatus == TaskStatus.Failure) {
                        return TaskStatus.Failure;
                    } else if (comparisonType == ComparisonType.Selector && executionStatus == TaskStatus.Success) {
                        return TaskStatus.Success;
                    }
                }
                return comparisonType == ComparisonType.Sequence ? TaskStatus.Success : TaskStatus.Failure;
            }
    
            public override void OnFixedUpdate()
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnFixedUpdate();
                }
            }
    
            public override void OnLateUpdate()
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnLateUpdate();
                }
            }
    
            public override void OnEnd()
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnEnd();
                }
            }
    
            public override void OnTriggerEnter(Collider other)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnTriggerEnter(other);
                }
            }
    
            public override void OnTriggerEnter2D(Collider2D other)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnTriggerEnter2D(other);
                }
            }
    
            public override void OnTriggerExit(Collider other)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnTriggerExit(other);
                }
            }
    
            public override void OnTriggerExit2D(Collider2D other)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnTriggerExit2D(other);
                }
            }
    
            public override void OnCollisionEnter(Collision collision)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnCollisionEnter(collision);
                }
            }
    
            public override void OnCollisionEnter2D(Collision2D collision)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnCollisionEnter2D(collision);
                }
            }
    
            public override void OnCollisionExit(Collision collision)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnCollisionExit(collision);
                }
            }
    
            public override void OnCollisionExit2D(Collision2D collision)
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnCollisionExit2D(collision);
                }
            }
    
            public override string OnDrawNodeText()
            {
                if (actions == null || !graphLabel) {
                    return string.Empty;
                }
    
                var text = string.Empty;
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    if (!string.IsNullOrEmpty(text)) {
                        text += "\n";
                    }
                    text += actions[i].GetType().Name;
                }
    
                return text;
            }
    
            public override void OnReset()
            {
                if (actions == null) {
                    return;
                }
    
                for (int i = 0; i < actions.Length; ++i) {
                    if (actions[i] == null) {
                        continue;
                    }
                    actions[i].OnReset();
                }
            }
        }
    }
    

    ParallelComplete

    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.")]
        [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)
            {
                if (currentChildIndex == 0) {
                    return TaskStatus.Success;
                }
                // Return the child task's status as soon as a child task returns success or failure.
                for (int i = 0; i < currentChildIndex; ++i) {
                    if (executionStatus[i] == TaskStatus.Success || executionStatus[i] == TaskStatus.Failure) {
                        return executionStatus[i];
                    }
                }
                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;
            }
        }
    }
    

    RandomSelector

    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.")]
        [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<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 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;
                }
            }
        }
    }
    

    Sequence

    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.")]
        [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;
            }
        }
    }
    

    StackedConditional

    using UnityEngine;
    
    namespace BehaviorDesigner.Runtime.Tasks
    {
        [TaskDescription("Allows multiple conditional tasks to be added to a single node.")]
        [TaskIcon("{SkinColor}StackedConditionalIcon.png")]
        public class StackedConditional : Conditional
        {
            [InspectTask]
            public Conditional[] conditionals;
            public enum ComparisonType
            {
                Sequence,
                Selector
            }
            [Tooltip("Specifies if the tasks should be traversed with an AND (Sequence) or an OR (Selector).")]
            public ComparisonType comparisonType;
            [Tooltip("Should the tasks be labeled within the graph?")]
            public bool graphLabel;
    
            public override void OnAwake()
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
    
                    conditionals[i].GameObject = gameObject;
                    conditionals[i].Transform = transform;
                    conditionals[i].Owner = Owner;
    #if UNITY_EDITOR || DLL_RELEASE || DLL_DEBUG
                    conditionals[i].NodeData = new NodeData();
    #endif
                    conditionals[i].OnAwake();
                }
            }
    
            public override void OnStart()
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnStart();
                }
            }
    
            public override TaskStatus OnUpdate()
            {
                if (conditionals == null) {
                    return TaskStatus.Failure;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    var executionStatus = conditionals[i].OnUpdate();
    #if UNITY_EDITOR || DLL_RELEASE || DLL_DEBUG
                    conditionals[i].NodeData.ExecutionStatus = executionStatus;
                    if (conditionals[i].NodeData.ExecutionStatus == TaskStatus.Running) {
                        Debug.LogWarning("Warning: The conditional task returned a status of running when conditional tasks should only return success or failure.");
                    }
    #endif
                    if (comparisonType == ComparisonType.Sequence && executionStatus == TaskStatus.Failure) {
                        return TaskStatus.Failure;
                    } else if (comparisonType == ComparisonType.Selector && executionStatus == TaskStatus.Success) {
                        return TaskStatus.Success;
                    }
                }
                return comparisonType == ComparisonType.Sequence ? TaskStatus.Success : TaskStatus.Failure;
            }
    
            public override void OnFixedUpdate()
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnFixedUpdate();
                }
            }
    
            public override void OnLateUpdate()
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnLateUpdate();
                }
            }
    
            public override void OnEnd()
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnEnd();
                }
            }
    
            public override void OnTriggerEnter(Collider other)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnTriggerEnter(other);
                }
            }
    
            public override void OnTriggerEnter2D(Collider2D other)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnTriggerEnter2D(other);
                }
            }
    
            public override void OnTriggerExit(Collider other)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnTriggerExit(other);
                }
            }
    
            public override void OnTriggerExit2D(Collider2D other)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnTriggerExit2D(other);
                }
            }
    
            public override void OnCollisionEnter(Collision collision)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnCollisionEnter(collision);
                }
            }
    
            public override void OnCollisionEnter2D(Collision2D collision)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnCollisionEnter2D(collision);
                }
            }
    
            public override void OnCollisionExit(Collision collision)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnCollisionExit(collision);
                }
            }
    
            public override void OnCollisionExit2D(Collision2D collision)
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnCollisionExit2D(collision);
                }
            }
    
            public override string OnDrawNodeText()
            {
                if (conditionals == null || !graphLabel) {
                    return string.Empty;
                }
    
                var text = string.Empty;
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    if (!string.IsNullOrEmpty(text)) {
                        text += "\n";
                    }
                    text += conditionals[i].GetType().Name;
                }
    
                return text;
            }
    
            public override void OnReset()
            {
                if (conditionals == null) {
                    return;
                }
    
                for (int i = 0; i < conditionals.Length; ++i) {
                    if (conditionals[i] == null) {
                        continue;
                    }
                    conditionals[i].OnReset();
                }
            }
        }
    }
    

    ConditionalEvaluator

    namespace BehaviorDesigner.Runtime.Tasks
    {
        [TaskDescription("Evaluates the specified conditional task. If the conditional task returns success then the child task is run and the child status is returned. If the conditional task does not " +
                         "return success then the child task is not run and a failure status is immediately returned.")]
        [TaskIcon("{SkinColor}ConditionalEvaluatorIcon.png")]
        public class ConditionalEvaluator : Decorator
        {
            [Tooltip("Should the conditional task be reevaluated every tick?")]
            public SharedBool reevaluate;
            [InspectTask]
            [Tooltip("The conditional task to evaluate")]
            public Conditional conditionalTask;
            [Tooltip("Should the inspected conditional task be labeled within the graph?")]
            public bool graphLabel;
    
            // The status of the child after it has finished running.
            private TaskStatus executionStatus = TaskStatus.Inactive;
            private bool checkConditionalTask = true;
            private bool conditionalTaskFailed = false;
    
            public override void OnAwake()
            {
                if (conditionalTask != null) {
                    conditionalTask.Owner = Owner;
                    conditionalTask.GameObject = gameObject;
                    conditionalTask.Transform = transform;
                    conditionalTask.OnAwake();
                }
            }
    
            public override void OnStart()
            {
                if (conditionalTask != null) {
                    conditionalTask.OnStart();
                }
            }
    
            public override bool CanExecute()
            {
                // CanExecute is called when checking the condition within a while loop so it will be called at least twice. Ensure the conditional task is checked only once
                if (checkConditionalTask) {
                    checkConditionalTask = false;
                    OnUpdate();
                }
    
                if (conditionalTaskFailed) {
                    return false;
                }
                return executionStatus == TaskStatus.Inactive || executionStatus == TaskStatus.Running;
            }
    
            public override bool CanReevaluate()
            {
                return reevaluate.Value;
            }
    
            public override TaskStatus OnUpdate()
            {
                var childStatus = conditionalTask.OnUpdate();
                conditionalTaskFailed = conditionalTask == null || childStatus == TaskStatus.Failure;
                return childStatus;
            }
    
            public override void OnChildExecuted(TaskStatus childStatus)
            {
                // Update the execution status after a child has finished running.
                executionStatus = childStatus;
            }
    
            public override TaskStatus OverrideStatus()
            {
                // This version of OverrideStatus is called when the conditional evaluator fails reevaluation and has to stop all of its children.
                // Therefore, the return status will always be failure
                return TaskStatus.Failure;
            }
    
            public override TaskStatus OverrideStatus(TaskStatus status)
            {
                if (conditionalTaskFailed)
                    return TaskStatus.Failure;
                return status;
            }
    
            public override void OnEnd()
            {
                // Reset the variables back to their starting values.
                executionStatus = TaskStatus.Inactive;
                checkConditionalTask = true;
                conditionalTaskFailed = false;
                if (conditionalTask != null) {
                    conditionalTask.OnEnd();
                }
            }
    
            public override string OnDrawNodeText()
            {
                if (conditionalTask == null || !graphLabel) {
                    return string.Empty;
                }
    
                return conditionalTask.GetType().Name;
            }
    
            public override void OnReset()
            {
                // Reset the public properties back to their original values.
                conditionalTask = null;
            }
        }
    }
    

    ReturnSuccess

    namespace BehaviorDesigner.Runtime.Tasks
    {
        [TaskDescription("The return success task will always return success except when the child task is running.")]
        [TaskIcon("{SkinColor}ReturnSuccessIcon.png")]
        public class ReturnSuccess : Decorator
        {
            // The status of the child after it has finished running.
            private TaskStatus executionStatus = TaskStatus.Inactive;
    
            public override bool CanExecute()
            {
                // Continue executing until the child task returns success or failure.
                return executionStatus == TaskStatus.Inactive || executionStatus == TaskStatus.Running;
            }
    
            public override void OnChildExecuted(TaskStatus childStatus)
            {
                // Update the execution status after a child has finished running.
                executionStatus = childStatus;
            }
    
            public override TaskStatus Decorate(TaskStatus status)
            {
                // Return success even if the child task returned failure.
                if (status == TaskStatus.Failure) {
                    return TaskStatus.Success;
                }
                return status;
            }
    
            public override void OnEnd()
            {
                // Reset the execution status back to its starting values.
                executionStatus = TaskStatus.Inactive;
            }
        }
    }
    

    UntilSuccess

    namespace BehaviorDesigner.Runtime.Tasks
    {
        [TaskDescription("The until success task will keep executing its child task until the child task returns success.")]
        [TaskIcon("{SkinColor}UntilSuccessIcon.png")]
        public class UntilSuccess : Decorator
        {
            // The status of the child after it has finished running.
            private TaskStatus executionStatus = TaskStatus.Inactive;
    
            public override bool CanExecute()
            {
                // Keep running until the child task returns success.
                return executionStatus == TaskStatus.Failure || executionStatus == TaskStatus.Inactive;
            }
    
            public override void OnChildExecuted(TaskStatus childStatus)
            {
                // Update the execution status after a child has finished running.
                executionStatus = childStatus;
            }
    
            public override void OnEnd()
            {
                // Reset the execution status back to its starting values.
                executionStatus = TaskStatus.Inactive;
            }
        }
    }
    

    GetAcceleration

    using UnityEngine;
    using UnityEngine.AI;
    
    namespace BehaviorDesigner.Runtime.Tasks.Unity.UnityNavMeshAgent
    {
        [TaskCategory("Unity/NavMeshAgent")]
        [TaskDescription("Gets the maximum acceleration of an agent as it follows a path, given in units / sec^2.. Returns Success.")]
        public class GetAcceleration : Action
        {
            [Tooltip("The GameObject that the task operates on. If null the task GameObject is used.")]
            public SharedGameObject targetGameObject;
            [SharedRequired]
            [Tooltip("The NavMeshAgent acceleration")]
            public SharedFloat storeValue;
    
            // cache the navmeshagent component
            private NavMeshAgent navMeshAgent;
            private GameObject prevGameObject;
    
            public override void OnStart()
            {
                var currentGameObject = GetDefaultGameObject(targetGameObject.Value);
                if (currentGameObject != prevGameObject) {
                    navMeshAgent = currentGameObject.GetComponent<NavMeshAgent>();
                    prevGameObject = currentGameObject;
                }
            }
    
            public override TaskStatus OnUpdate()
            {
                if (navMeshAgent == null) {
                    Debug.LogWarning("NavMeshAgent is null");
                    return TaskStatus.Failure;
                }
    
                storeValue.Value = navMeshAgent.acceleration;
    
                return TaskStatus.Success;
            }
    
            public override void OnReset()
            {
                targetGameObject = null;
                storeValue = 0;
            }
        }
    }
    

    三、效果展示



    相关文章

      网友评论

          本文标题:OpenXR开发实战项目之VR BehaviorDesinger

          本文链接:https://www.haomeiwen.com/subject/ihlpgdtx.html