Unity行为树插件BehaviorDesigner

BehaviorDesigner——行为树,用于控制和实现AI逻辑
在这里插入图片描述

一 Behavior:这个行为树的设置

二 Tasks:行为树的所有节点Tasks

Behavior Designer插件里,主要有四种概念节点,都称之为Task。包括:

(1) Composites 组合节点

包括经典的:Sequence,Selector,Parallel

在这里插入图片描述

Abort Type 中止类型

复合类Task的优先级和打断:

这一点非常重要,是复合类Task的唯一特殊属性:分为四种——不打断,可打断自身,可打断低于该Task优先级的其他Task,既可以打断自身也可以打断低于其优先级的。
在这里插入图片描述
需要注意的是,该复合节点的打断条件是其下子节点必须有条件节点,此时该条件节点的判断一直处于运行状态,一旦该条件节点在某一刻发生改变,此时行为树将重新跳转到该复合节点位置继续运行,从而打断其他正在运行的低优先级节点。

(2) Decorator 装饰节点

,顾名思义,就是为仅有的一个子节点额外添加一些功能,
比如让子task一直运行直到其返回某个运行状态值,或者将task的返回值取反等等

(3) Actions 行为节点

,行为节点是真正做事的节点,其为叶节点。Behavior Designer插件中自带了不少 Action节点,如果不够用,也可以编写自己的Action。一般来说都要编写自己的Action,
除非用户是一个不懂脚本的美术或者策划,只想简单地控制一些物件的属性。

(4) Conditinals 条件节点

,用于判断某条件是否成立。目前看来,是Behavior Designer为了贯彻职责单一的原则,
将判断专门作为一个节点独立处理,比如判断某目标是否在视野内,其实在攻击的Action里面也可以写,但是这样
Action就不单一了,不利于视野判断处理的复用。一般条件节点出现在Sequence控制节点中,其后紧跟条件成立后的Action节点。

自定义Task任务:

一般复合类和装饰类的Task是够用的,甚至有些根本用不到,而具体的行为类Task和条件类Task从来都不能满足我们的需求,而且自己写这类Task可以很大程度的简化整个行为树结构。

自己写Task的步骤如下:

1.引入命名空间:
	1  using BehaviorDesigner.Runtime;
	2  using BehaviorDesigner.Runtime.Tasks;
2.明确继承的Task类型:
	1   public class MyInputMove : Action
	2   public class MyIsInput : Conditional

在这里插入图片描述
观察上图就会发现和Unity中编写脚本大同小异,不一样的地方就是这里的Update有返回值,要返回该任务的执行状态,只有在Running状态时才每帧调用。

using UnityEngine;
using BehaviorDesigner.Runtime;
using BehaviorDesigner.Runtime.Tasks;

public class MyInputMove : Action
{
    public SharedFloat speed = 5f;
    public override TaskStatus OnUpdate()
    {
        float inputX = Input.GetAxis("Horizontal");
        float inputZ = Input.GetAxis("Vertical");
        if (inputX != 0 || inputZ != 0)
        {
            Vector3 movement = new Vector3(inputX, 0, inputZ);
            transform.Translate(movement*Time.deltaTime*speed.Value);
            return TaskStatus.Running;
        }
        return TaskStatus.Success;
    }
}

还有一点不同,就是Task中封装了一层Share的类型的属性,它和非Share类型有何区别呢?
下面是对比:

using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime;

public class MyLog : Action
{
    public string staticLog;
    public SharedString shareLog;

    public override TaskStatus OnUpdate()
    {
        Debug.Log(staticLog + shareLog.Value);
        return TaskStatus.Success;
    }
}

还有一点不同,就是Task中封装了一层Share的类型的属性,它和非Share类型有何区别呢?
下面是对比:

using UnityEngine;
using BehaviorDesigner.Runtime.Tasks;
using BehaviorDesigner.Runtime;
public class MyLog : Action
{
    public string staticLog;
    public SharedString shareLog;
    public override TaskStatus OnUpdate()
    {
        Debug.Log(staticLog + shareLog.Value);
        return TaskStatus.Success;
    }
}

在这里插入图片描述
在这里插入图片描述
可以看到,这里的Share的类型就是一个方便在行为树中传递和修改的变量,因为Task之间是不方便直接修改其他Task变量的,那怎么办呢,于是就增加一种Share的类型变量在行为树的各个Task之间进行交流。

比如这里,每次找到的最近的敌人是不一样的,要根据上一个Task返回的值去执行下一个Task的攻击或打印结果,这时固定的属性就无法满足要求,但直接调用别的Task又增加了耦合性,于是就单独用Share变量来传递值。这样也方便在面板中统一查看管理。

另外Share变量也可以增加自定义类型,全局的和本地变量的区别就是一个在所有的行为树中有,一个只有这棵树中有。

在取Share变量值时需要.Value。

三 Variables:行为树的 通用变量

	用于这个行为树所有节点间变量的 通信(比如A节点的是寻敌任务,寻找到敌人Target后把这
	个Target设置到通用变量中,B节点的任务从这个通用变量中拿到Target执行攻击任务

四 Inspector:

点击某个节点后,显示节点的详细信息,可以设置 public 变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值