Behavior Creator 行为树可视化编辑器

Behavior Creator 行为树可视化编辑器

  • 这是一款为 CocosCreator 深度定制的行为树可视化编辑器插件
  • 已实现 SelectorSequenceParallel 三种组合节点
  • 已实现 ConditionalDecorator 两种装饰器
  • 已实现 Service 服务类型
  • 已实现 Task 任务类型
  • 支持自定义节点注册到行为树编辑器
  • 支持类属性差异化更新
  • 支持节点生命周期 onEnableonUpdateonDisable 等通用事件委托

注意

  • 仅支持在 CocosCreator v3.3.0 及以上版本中使用

效果预览

快速开始

  • CocosCreator 编辑器菜单 扩展 --> 商城 中搜索 BehaviorCreator 即可找到该插件,购买后下载到本地

  • 导入插件 oreo-behavior-creator 并启用

    image-20220427172931847

  • 资源管理器 面板中看到 oreo-behavior-creator 运行时 已载入,则表示插件导入成功

    image-20220427173208187

  • 注意,因插件需要导入运行时脚本,在CocosCreator编辑器已打开状态下可能会出现以下错误,此时需要重启编辑器

插件入口

  • 行为树编辑器是由 json 数据驱动的,其入口已集成到 BehaviorTree 组件的属性检查器面板,可通过以下方式启动

    1. 新建空节点,在节点上挂载 BehaviorTree 组件

    2. 新建内容为空{}json资源,并关联到 BehaviorTreeJsonAsset 属性。点击 Edit Behavior 即可打开行为树编辑器

加载示例

  • 在运行时目录extensions\oreo-behavior-creator\runtime\examples\data 中提供了一些简单示例,可以通过 Load 菜单加载到行为树编辑区,Save 保存后下一步运行查看效果。

运行效果

  • BehaviorTree 组件默认是没有启用 LogTaskChanges 属性的,我们先勾选以便在控制台输出 log。

    注:当行为树某次执行结果不是 Running 状态时,本次运行结束。如果需要重新开始,需要勾选 RestartWhenComplete

示例分析

巡逻行为分析

  • 我们设定一次巡逻主要包括以下逻辑

    1. 在指定区域目标点之间来回移动

      通用 Task 任务节点

    2. 到达指定点后原地休息等待一段时间

      Wait 任务节点

  • 由于上述是一个连续有序的行为,因此需要将它们挂载到 Sequence 父节点

    Sequence 序列节点

  • 整体巡逻行为如图所示

场景搭建

代码逻辑

  • 随机移动

    在巡逻行为树结构中,随机移动 节点是一个通用 Task 任务节点,需要我们定制 onUpdate 任务更新逻辑。

    新建 AIEnemy.ts 组件类并实现找点随机移动逻辑,挂载到 AIEnemy 场景节点上。主要逻辑包含两点:

    1、到达目标点时返回 Success 表示成功,由父节点 Sequence 顺序执行下一个子节点的行为,即 原地休息

    2、未到达目标点时返回 Running 表示任务还在持续,由父节点 Sequence 下一次 tick 继续执行

    具体实现如下:

    onRandomMove(){
        this._playAnim("run", 1);
    
        //这里为了方便,只是按点索引顺序移动
        let point = this.patrolPoints[this._index];
        //自身点位置
        pos1.set(this.target.position);
        //目标点位置
        pos2.set(point.position);
    	//朝向
        this.target.lookAt(pos2);
    
        //目标点达标与否阈值判断
        if(Vec3.distance(pos1, pos2) < 0.1){
            this._index++;
            if(this._index>=this.patrolPoints.length){
                this._index = 0;
            }
    
            this._playAnim("idle");
            //到达目标点时返回成功,由父节点 `Sequence` 顺序执行下一个子节点的行为,即 `原地休息`
            return bt.BehaviorStatus.Success;
        }
        else{
            let pos = this.lerp(out, pos1, pos2, 0.02);
            this.target.setPosition(pos);  
    
    		//未到达目标点时返回 Running ,由父节点 `Sequence` 下一次 tick 继续执行
            return bt.BehaviorStatus.Running;  
        }
    }
    
  • 原地休息

    这是一个内置 Wait 任务节点,主要作用就是在指定时间内任务直接返回 Running 状态,表示任务还在持续,时间到达后返回 Success 表示任务完成。

    Wait 任务有一个 duration 属性,表示任务持续时间。这是一个 SharedVariable 共享变量属性,与Blackboard黑板变量关联。

逻辑绑定

  • 我们先来指定 原地休息 时间

    新建一个 SharedNumber 数字类型的黑板共享变量,值设定为 2,并指定给 duration 属性,表示原地休息 2 秒

  • 绑定 随机移动 任务的 onUpdate 委托逻辑。

    如图,将 onUpdate 逻辑绑定到 AIEnemy 组件的 onRandomMove 方法

    Delegate 委托逻辑绑定与 CocosCreator 内置按钮事件绑定过程相似

运行效果

  • 首次运行效果如下

  • 我们发现AI 移动到指定目标点且原地休息结束后,并没有继续移动到下一个目标点。这是因为,对于本次行为来说,Wait 执行结束并返回 Success 状态,表示行为树已经全部执行完毕。如果需要重新开始,只需勾选 BehaviorTree 组件上的 RestartWhenComplete

    image-20220428000209459

  • 最终效果如下

追逐行为分析

  • 我们设定一次追逐主要包括以下逻辑

    1. 当玩家出现在 AIEnemy 的感应区域内时,AIEnemy 立即移动并靠近玩家

      通用 Task 任务节点

    2. 当玩家被追逐达到受击范围时,AIEnemy 发动一次攻击。我们设定一次攻击包含实际攻击和技能CD两个任务。

      Sequence 序列节点,通用 Task 任务节点、Wait 任务节点

  • 由于靠近一次攻击 是区分条件执行(不在受击范围就靠近,在受在范围就攻击),即一次只会执行一个分支,因此需要将它们挂载到 Selector 父节点

    Selector 序列节点

  • 此时追逐玩家行为如图所示

场景搭建

代码逻辑

  • 靠近

    靠近 节点也是一个通用 Task 任务节点,需要我们定制 onUpdate 任务更新逻辑。

    更新 AIEnemy.ts 组件类并实现相关逻辑。主要逻辑包含:

    1、判断玩家是否在受击范围内

    2、不在范围内则靠近

    3、在范围内则攻击

    范围判断:

    canAttack(){
        //当前位置
        pos1.set(this.target.position);
        //玩家位置
        pos2.set(this.player.position);
    
        //受击范围判断
        if(Vec3.distance(pos1, pos2) < 1){
            return bt.BehaviorStatus.Success;
        }
    
        return bt.BehaviorStatus.Failure;
    }
    

    移动到攻击范围

    onMoveToAttack(){
        if(this.canAttack()==bt.BehaviorStatus.Success){
            return bt.BehaviorStatus.Failure;
        }
        else{
            pos1.set(this.target.position);
            pos2.set(this.player.position);
            this.target.lookAt(pos2);
    
            let pos = this.lerp(out, pos1, pos2, 0.03);
            this.target.setPosition(pos);
    
            this._playAnim("runHit");
            return bt.BehaviorStatus.Running;
        }
    }
    

    发动攻击

    onAttack(){
        this._playAnim("attackLeft");
        //一次攻击结束后等待技能冷却,所以在攻击动作结束后播放防御动画 'fightIdel'
        this.anim.once(AnimationComponent.EventType.LASTFRAME, ()=>{
            this._playAnim("fightIdle");
        })
        //主角受击
        this.aiPlayer.beAttacked();
        return bt.BehaviorStatus.Success;
    }
    

    技能CD

    这也是一个内置 Wait 任务节点,与上一节中 巡逻 行为的 原地休息 节点类似,只需指定持续时间 duration 即可

逻辑绑定

  • 分别绑定 靠近攻击 任务的 onUpdate 委托逻辑。

    image-20220427233042108

  • 本次运行效果如下

    我们看到,AI 启动后立即向玩家靠近,这不太科学。我们给 AI 添加一个感应区域作为 AI 的视野,当玩家出现在感应区域范围内时 AI 才奔向玩家。

    1. 我们使用内置的 Conditional 条件元素来实现条件判断

    2. 视野判断代码实现

      onHasSight(){
          //当前位置
          pos1.set(this.target.position);
          //玩家位置
          pos2.set(this.player.position);
      
          //视野范围
          if(Vec3.distance(pos1, pos2) < 8){
              return bt.BehaviorStatus.Success;
          }
      
          return bt.BehaviorStatus.Failure;
      }
      
    3. 绑定 onUpdate 逻辑

运行效果

  • 增加视野判断后,运行效果如下

    圆形区域为 AI 视野,当玩家进入视野时,AI 开始追逐,当追逐到玩家受击范围时,展开攻击。

下一步

加入

  • BehaviorCreator QQ交流群:
  • 659064495

说明

  • 压缩包内包含完整运行时源码以及示例项目工程,详见包内 Readme.md 文档
12赞

1楼!带带弟弟!

熟悉的口号!感谢支持 [手动玫瑰]。
插件上新,限时大力优惠中。

还能说啥呢,强强强强

:smiley: :smiley:
支持大佬, 要是可以把示例放在 runtime 里面就好了,
刚刚下载插件的时候, 有点懵, 不知道该看哪里, 如果可以的话, 加个菜单栏可能好一点,
仔细找了一下, 终于找到示例了, 感谢大佬.

安排,我加个菜单。

关于示例的话,我也在菜单里加些引导。目前主要还是考虑有些插件无关的改动我可以直接提交仓库,大家直接拉取回来就可以了。

1赞

:laughing: :+1:

v1.0.1更新

  • 支持 prefab 预制体节点数据绑定
  • 在事件绑定中获取节点身上挂载的组件时,过滤引擎部分内部组件,避免与插件无关的报错
  • 编辑区数据检测,有修改时面板标题增加 * 星号标志,退出时提示保存
  • 增加 CocosCreator 菜单入口(面板 -> oreo-behavior-creator),展示相关说明,方便新用户上手

v1.0.2更新

  • 支持场景中行为树节点复制,自动更新节点绑定数据(多个AI节点可共用一份json数据)
1赞

v1.0.3更新

2赞

很实用,大佬

在商店买了您的插件,请加一下我。

想问一下支持行为树的中断功能码?

如上图所示,支持三种中断类型。

具体可以看下对应文档: 行为中断

我很好奇为什么官方不做行为树、状态机、shader可视化编辑器 @jare

因为3D基础功能官方都没做完,一旦做完就要维护。
unity官方也没做行为树这个靠社区目前也有2 3个成品了。至于状态机,这玩意也不用官方做吧,state模式很简单了,配合现在的动作编辑器也够了。
shader可视化编辑感觉和3D没做完一个意思,官方上一个版本才支持LOD,我感觉距离处理shader还有3-5年 :crazy_face:

主要是官方做的感觉保障性比较强,哪怕出个shader可视化编辑器插件要999买起来都没有问题,如果是个人开发者就基本不会买了,主要还是个人开发者无法确定其后续维护性

我觉得官方可以做些开发常用插件进行收费,这个也是项目组自身进行职能创收 @jare shader可视化编辑器真的非常需要

请教。你的行为树怎么暂停? cocoscreator 3.7.1 ;

两种方式:

  1. 使用 BehaviorManager 的 pauseBehavior 方法
  2. 行为树自身根节点入口挂一个条件装饰器做控制