这个类型的节点只能有一个子节点。它的功能是修改子任务的行为。在上面的例子中,我们没有使用 decorator(修饰符),如果你需要类似于打断操作的话会用得到这个 decorator(修饰符)类型!举个例子:一个收集资源的操作,它可能有一个中断节点,这个节点判断是否被攻击,如果被攻击则中断收集资源操作!decorator(修饰符)的另一个应用场合是重复执行子任务 X 次,或
//一个父任务可以拥有的子任务的最大数量。通常为1或int。MaxValue
public virtual int MaxChildren();
//布尔值,以确定当前任务是否为并行任务
public virtual bool CanRunParallelChildren();
//当前活动子节点的索引
public virtual int CurrentChildIndex();
//布尔值,以确定当前任务是否可以执行
public virtual bool CanExecute();
//为执行状态应用装饰器,输入参数为被修饰节点的状态
public virtual TaskStatus Decorate(TaskStatus status);
//通知parenttask子任务已被执行,其状态为childStatus
public virtual void OnChildExecuted(TaskStatus childStatus);
//通知父任务,其子任务childIndex已被执行,其状态为childStatus
public virtual void OnChildExecuted(int childIndex, TaskStatus childStatus);
//通知任务子进程已经开始运行
public virtual void OnChildStarted();
//通知并行任务,索引为childIndex的子任务已开始运行
public virtual void OnChildStarted(int childIndex);
//一些父任务需要能够覆盖状态,例如并行任务
public virtual TaskStatus OverrideStatus(TaskStatus status);
//如果中断节点被中断,它将覆盖状态。
public virtual TaskStatus OverrideStatus();
//通知复合任务,条件中止已被触发,子索引应重置
public virtual void OnConditionalAbort(int childIndex);
条件节点的终止
一共有四种中断类型的 abort types: None, Self, Lower Priority, and Both.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
public class MyMoveTo : Action
{
public GameObject enemy;
public override TaskStatus OnUpdate()
{
if (GetComponent())
{
if (Vector3.Distance(transform.position, enemy.transform.position) < 0.1f)
{
return TaskStatus.Success;
}
else
{
transform.position = Vector3.MoveTowards(transform.position,enemy.transform.position,Time.deltaTime);
return TaskStatus.Running;
}
}
else
{
return TaskStatus.Failure;
}
}
}
自定义条件节点
同样引入命名空间,然后继承Conditional
判断敌人是否存活,如果否,那么返回Failure
public class MyConditional : Conditional
{
public GameObject enemy;
public override TaskStatus OnUpdate()
{
if (enemy.GetComponent().alive)
{
return TaskStatus.Success;
}
else
{
return TaskStatus.Failure;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
public class BT_Test : MonoBehaviour
{
public bool on;
public BehaviorTree behaviorTree;
public void Start()
{
behaviorTree = GetComponent();
behaviorTree.StartWhenEnabled = false;
}
public void Update()
{
if (on)
{
behaviorTree.EnableBehavior();
on = false;
}
}
}
Event事件
为了说明事件,我们使用下面这个行为树
这里我们使用了一个条件节点:Has Received Event
通过该条件节点的Inspector界面,我们可以看到,它有一个属性和三个变量
Event 事件名称
参数
我们来看看他的源码的一个函数
很明显,在行为树启动时,他会自动以给定的名称来注册事件,一共有四种注册事件(0个参数到3个参数)
public override void OnStart()
{
// Let the behavior tree know that we are interested in receiving the event specified
if (!registered) {
Owner.RegisterEvent(eventName.Value, ReceivedEvent);
Owner.RegisterEvent
我们通过一个脚本来调用函数,调用对应的事件十分简单,因为我们使用了一个名字来注册事件,想要调用只需要使用behaviorTree.SendEvent()这个API即可调用,也就是发送,调用了它之后,Has Received Event条件节点就会返回Success,因此条件能够通过,你可以把这个函数当作对应名字事件的触发器,触发即可使得该条件节点返回Success。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;
public class TaskA : MonoBehaviour
{
public bool send;
public bool on;
public BehaviorTree behaviorTree;
public void Start()
{
behaviorTree = GetComponent();
behaviorTree.StartWhenEnabled = false;
}
public void Update()
{
if (on)
{
behaviorTree.EnableBehavior();
on = false;
}
if (send)
{
behaviorTree.SendEvent("MyEvent",1);
send = false;
}
}
}
行为树运行后,还未收到事件调用信息,此时我们使用Wait防止行为树结束,保持运行
我们发送信息后,条件节点收到信息后,通过执行
Task的引用
我们先创建两个行为节点,并在一个节点中创建第二个节点公共变量,并尝试打印信息
public class TaskF : Action
{
public TaskS referencedTask;
public override void OnAwake()
{
Debug.Log(referencedTask.some);
}
}
public class TaskS : Action
{
public float some;
}
我们来看看Inspector界面
在属性界面,它显示出了一个引用任务的选择按钮,因为对于行为节点我们无法直接赋值,因此采取选择的方式
点击Select,然后点击行为树中对应类型的行为节点,此时就是将选中行为节点赋予给本节点的此变量
通过点击X,可以取消引用
在引用后,我们启动行为树就会正常打印,如果不引用就会报出空指针异常。
变量同步器(Variable Synchronizer)
同步全局变量,箭头表示同步方向,下图中就是将A的值同步给B,点按Add添加同步操作
添加之后,仍然可以改变同步方向,点按箭头按钮即可,启动后才能看到同步效果
Task可用特性
HelpURL : web 连接
[HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=27")]
public class Parallel : Composite{
}
TaskIcon :任务的图标
[TaskIcon("Assets/Path/To/{SkinColor}Icon.png")]
public class MyTask : Action{
}
TaskCategory:任务的显示位置(在 Task 任务面板中的显示位置)
[TaskCategory("Common")]
public class Seek : Action{
}
[TaskCategory("RTS/Harvester")]
public class HarvestGold : Action{
}
TaskDescription:功能描述的文本内容,显示在编辑器布局区域的左下角
[TaskDescription("The sequence task is similar to an \"and\" operation. ..."]
public class Sequence : Composite{
}
LinkedTask:应用其他的 Task 任务
[LinkedTask]
public TaskGuard[] linkedTaskGuards = **null**;
只需要在调用该对象合适(比如下列的setStyles)的方法后让该方法返回该对象(通过this 因为一旦一个函数称为一个对象方法的话那么在这个方法内部this(结合下面的setStyles)指向这个对象)
function create(type){
var element=document.createElement(type);
//this=element;
JAX-WS
SOAP Version 1.2 Part 0: Primer (Second Edition)
SOAP Version 1.2 Part 1: Messaging Framework (Second Edition)
SOAP Version 1.2 Part 2: Adjuncts (Second Edition)
Which style of WSDL
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml