手动写一个Behavior Designer任务节点

来源:互联网 发布:掌握了c语言之后学什么 编辑:程序博客网 时间:2024/06/05 06:24

转自:  http://blog.csdn.net/qq_33747722/article/details/53539532

转自:  https://my.oschina.net/acitiviti/blog/625799


在Behavior Designer的可视化节点实际都是由脚本语言编写出来的

自己手写一个类似于CanSeeObject、Seek等任务节点并不是一件难事.

下面我介绍CanSeeObject和Seek任务节点的代码生成,基本成功实现了原来节点的功能

LJLCanSeeObject代码如下:

using UnityEngine;  using System.Collections;  using BehaviorDesigner.Runtime;  using BehaviorDesigner.Runtime.Tasks;   #region 检测选中的游戏对象是否在视野内    /// <summary>  ///CanSeeObject是在Conditional下的节点,因此自己手动写的一个类似于CanSeeObject的节点继承自Conditional,在这里命名为LJLCanSeeObject  /// </summary>  public class LJLCanSeeObject : Conditional  {      /// <summary>      /// 视野内检测的目标对象      /// </summary>      public Transform[] targets;      /// <summary>      /// 视野角度      /// </summary>      public float fieldOfViewAngle = 90;      /// <summary>      /// 视野距离(共享变量)      /// </summary>      public SharedFloat sharedViewDistance;      /// <summary>      /// 在视野内检测到的游戏对象位置(共享变量,在这里将检测到的游戏对象位置数据附给它)      /// </summary>      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 < sharedViewDistance.Value && angle < fieldOfViewAngle * 0.5f)              {                  //将检测到的游戏对象位置数据附给共享变量                  this.target.Value = target;                  return TaskStatus.Success;              }          }          return TaskStatus.Failure;      }  }   #endregion  

LJLSeek代码如下:

using UnityEngine;  using System.Collections;  using BehaviorDesigner.Runtime;  using BehaviorDesigner.Runtime.Tasks;   #region 控制游戏物体到达目标位置    public class MySeek : Action   {      /// <summary>      /// 行走速度(共享变量)      /// </summary>      public SharedFloat sharedSpeed;      /// <summary>      /// 目标位置(共享变量)      /// </summary>      public SharedTransform target;      /// <summary>      /// 到达目的地的距离(共享变量)      /// </summary>      public SharedFloat sharedArriveDistance = 0.1f;      private float sqrArriveDistance;        public override void OnStart()       {          sqrArriveDistance = sharedArriveDistance.Value*sharedArriveDistance.Value;      }          //当进入到这个任务的时候,会一直调用这个方法,直到任务结束       //返回一个 Success 或者 Failure 的状态,那么任务结束       //返回一个Running的状态,则这个方法会继续调用      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, sharedSpeed.Value*Time.deltaTime);            if ((target.Value.position - transform.position).sqrMagnitude < sqrArriveDistance)           {              //当距离目标位置的距离比较小时,认为到达了目标位置,直接return成功              return TaskStatus.Success;          }            return TaskStatus.Running;      }  }  #endregion  

接下来Conditionals条件节点有个LJLCanSeeObject节点可以选择使用。

Actions行为节点有个LJLSeek节点可以选择使用。

行为树是一组任务的集合。任务拥有和unity MonoBehaviour 相似的API,所以他很容易的让你创建一个任务(创建任务将在后面章节详细讲解)。任务类有如下API:
// OnAwake is called once when the behavior tree is enabled. Think of it as a constructorpublic virtual void OnAwake();// OnStart is called immediately before execution. It is used to setup any variables that need to be reset from the previous runpublic virtual void OnStart();// OnUpdate runs the actual taskpublic virtual TaskStatus OnUpdate();// OnEnd is called after execution on a success or failure. public virtual void OnEnd();// OnPause is called when the behavior is paused and resumedpublic virtual void OnPause(bool paused);// The priority select will need to know this tasks priority of runningpublic virtual float GetPriority();// OnBehaviorComplete is called after the behavior tree finishes executingpublic virtual void OnBehaviorComplete();// OnReset is called by the inspector to reset the public propertiespublic virtual void OnReset();// Allow OnDrawGizmos to be called from the taskspublic virtual void OnDrawGizmos();// Keep a reference to the behavior that owns this taskpublic Behavior Owner;

 任务有三个共有的属性:名称,注释,瞬时状态。瞬时状态是三个属性中一个不太容易理解的属性。在一个相同的循环周期中,一个任务返回成功或者失败后,任务将立刻运行下一个任务,先前的任务将处于等待状态。这种模式有利于减少行为树性能消耗。

     下图显示了任务运行的流程:



0 0