npm 包 behavior3ts 使用教程

阅读时长 14 分钟读完

前言

行为树(Behavior Tree)是一种常用于游戏开发和人工智能领域的算法,相比传统的有限状态机(FSM)和任务队列(BT)等方法,它更加灵活和易于扩展。在前端开发领域,我们也经常需要使用行为树来实现复杂的用户交互逻辑等。

本文将介绍一款使用 TypeScript 实现的行为树框架 behavior3ts,通过实例演示其使用方法,帮助读者掌握行为树的编写和使用技巧。

安装与导入

behavior3ts 可以通过 npm 包管理工具来进行安装,只需在项目根目录中运行如下命令即可:

然后,在 TypeScript 代码中,我们需要通过引入 BehaviorTree、Composite、Decorator 等相关模块,来使用 behavior3ts 提供的各种类和方法:

行为树结构

行为树是由节点(Node)和连接线(Edge)组成的树形结构,其中每个节点代表一种行为或决策,每个连接线则代表行为之间的联系和逻辑顺序。行为树的结构一般分为三种类型:组合节点(Composite)、装饰节点(Decorator)和行为节点(Action/Condition)。

组合节点

组合节点是行为树中的容器节点,可以组合多个子节点,形成一个完整的行为序列。组合节点主要分为如下几类:

  • Sequence
  • Priority
  • Parallel
  • RandomSequence
  • RandomPriority
  • MemSequence
  • MemPriority

以 Sequence 为例,它将所有子节点按照顺序执行,只有当所有子节点都返回 success 才返回 success,否则返回 failure。实现这个结构,我们可以这样编码:

-- -------------------- ---- -------
-- --------
----- ------------ - --- ---------------- ------------------
----- ---------- - --- -------------

-- -------
----- -------------- ------- --------- -
  ------------- -
    --------
    ------------- - -
      --- ------------------------------- ----- --------- --- -- ---- -
      --- ------------------------------- ----- --------- --- -- ---- -
      --- ------------------------------- ----- --------- --- -- ---- -
    --
  -

  -- --------
  ------ ------------- --------------------- -
    ------ - ----------- ---------- --
  -
-

-- ---------
--------- --------------------- ------- ------------- -
  ----------- -----------
-

-- ------------ ------ --- -------- ----- ------------- -------- ---
----- -------- ------- ---------------------- ------- ------------- -
  ------ ------------------- ------- - ----- ------ -- -
    -------------------
  -
  --------- ----------------- --- ----- -
    --------------- ----------- ---------------
    ------ --------------
  -
-

组合节点的作用相当于编程语言中的分支结构,可以按照一定的规则判断子节点的执行顺序和停止条件。在 behavior3ts 中,组合节点还提供了多种预设的混合类型,可以更好地适配各种行为树需求。

装饰节点

装饰节点是行为树中的修饰性节点,可以用来修改或限制节点的执行情况,例如执行次数、执行时间、优先级等。装饰节点的常用类型有以下几种:

  • Repeater
  • MaxTime
  • Inverter
  • Succeeder
  • Failer
  • Error
  • UntilSuccess
  • UntilFailure

以 Repeater 为例,它将子节点无限次执行,直到某个子节点返回 failure 或达到指定执行次数为止。实现这个结构,我们可以这样编码:

-- -------------------- ---- -------
-- --------
----- ------------ - --- ---------------- ------------------
----- ---------- - --- -------------

-- -------
----- -------------- ------- -------------------------------- -
  ------------- -
    --------
    ---------- - --- ------------------------------- ----- -------- --- -- ----
    -------------- - --- --------------------------------- -------- - --- -- ----
  -

  -- --------
  ------ ------------- --------------------- -
    ------ - ----------- ---------- --
  -
-

-- ---------
--------- --------------------- ------- ------------- -
  ----------- -----------
-

-- ------------ ------ --- -------- ----- ------------- -------- ---
----- -------- ------- ---------------------- ------- ------------- -
  ------ ------------------- ------- - ----- ------ -- -
    -------------------
  -
  --------- ----------------- --- ----- -
    --------------- ----------- ---------------
    ------ --------------
  -
-

装饰节点的作用相当于编程语言中的函数或方法,可以对子节点进行递归或循环调用,并在适当的时候返回或传递数据。

行为节点

行为节点是行为树中的基本执行单元,用来实现具体的行为操作或状态判断。行为节点的类型一般分为 Action(直接执行某项操作)和 Condition(判断某项条件)两种。例如:

-- -------------------- ---- -------
-- ------------
----- -------- ------- --------------------------- -
  ------------------- ------- - ----- ------ -- -
    -------------------
  -
  --------- ----------------- ---------------- -
    --------------- ----------- ---------------
    ------ --------------
  -
-

-- ------------
----- ----------- ------- ------------------------------ -
  ------------------- ------- - ----- ------ -- -
    -------------------
  -
  --------- ----------------------- ---------------- -
    ------ -----
  -
-

-- -----
--------- --------------- ------- ------------- -
  -- ---
-

-- --------
----- -------- --------------- - - ----------- ---------- --

实际上,以上三种节点的区别并不是非常明显,它们的代码实现都很相似,都需要重写父类的 doAction 或 checkCondition 方法,并在其中进行具体的执行或判断操作。

实例演示

下面,我们通过一个实际的场景来演示 behavior3ts 的使用方法。该场景是一个玩具汽车遥控器的示例,用户可以通过控制器上的四个方向按钮,控制玩具车沿同一方向前进或后退。具体来说,该场景需要实现如下功能:

  • 当用户按下前进或后退按钮时,玩具车会向前或向后移动一定距离,然后停止。
  • 当用户再次按下同一方向的按钮时,玩具车会再次移动,直到再次按下另一方向的按钮或到达终点位置。
  • 当用户按下相反方向的按钮时,玩具车会停止前一种移动方式,立即转向并开始相反方向的移动。

按照上述需求,我们可以设计如下的行为树结构:

其中,Sequence 表示按一定的顺序执行两个子节点,Selector 表示按优先级执行两个子节点中的一项,Repeater 表示循环执行一个子节点,直到达到指定次数或条件不满足为止,Move 表示控制玩具车向前或向后移动一定距离,Wait 表示等待一段时间,Action 表示停止玩具车。

在代码中,我们可以这样实现这个行为树:

-- -------------------- ---- -------
------ - ------------- ----------- ---------- ---------- ------- ----- - ---- --------------

-- --------
----- ------------ - --- ---------------- ------------------
----- ---------- - --- -------------

-- -------
----- -------------- ------- -------------------------------- -
  ------------- -
    --------
    ------------- - -
      -- ----
      --- ---------------------------------
        --------- -
          -- ----
          --- ---------------------------------
            --------- -
              -- ----
              --- --------------------------------- ------ -- -- ----- -- - -------- - -- ------ -- ---
              -- ----
              --- ------------------------------- ----- ------ ---
            --
          ---
          -- ----
          --- ------------------------------- ----- --------- ---
        --
      ---
    --
  -

  -- --------
  ------ ------------- --------------------- -
    ------ - ----------- ---------- --
  -
-

-- ---------
--------- --------------------- ------- ------------- -
  ----------- -----------
  -- ----------- ------ ----- ---
  ---------- -------
  -- -------
  -- -------
  -- -------
  -------- -------
-

-- --------
----- ---- ------- ----------------------------- -
  --------- ----------------- ---------------------- -
    --------------- ----------- ---------------
    --------- -- ----------------- - ---
    ------ --------------
  -
-
----- ---- ------- ----------------------------- -
  --------- ----------------- ---------------------- -
    --------------- ----------- ---------------
    ------ --------------
  -
-
----- ---- ------- ----------------------------- -
  --------- ----------------- ---------------------- -
    --------------- ----------- ---------------
    ----------------- - --
    ------ --------------
  -
-
----- ------- ------- ----------------------------- -
  --------- ----------------- ---------------------- -
    --------------- ----------- ---------------
    ----------------- - --
    --------- - --
    --------------- - --
    ------ --------------
  -
-

-- -------------
--------------------------- -- ---
------------------- -- ---
------------------------- ---- ---
-- -----
--------------------

在上面的代码中,我们首先定义了一个行为树类 MyBehaviorTree,该类继承自 Composite 类,表示组合节点顺序执行两个子节点。其中,第一个子节点是一个 Selector 选择节点,表示按照一定的优先级执行两个子节点中的一个。具体来说,该选择节点包含了两个子节点:一个循环节点 Repeater,一个行为节点 Action。

循环节点 Repeater 表示按照一定的次数(如 3 次)执行一个子节点,该子节点在具体实现中,会判断当前行动方向(direction)并执行前进或后退操作。该循环节点包含了一个 Sequence 顺序节点,用来按照一定的顺序执行两个子节点:行动(Move)和等待(Wait)。行动节点 Move 的作用是让玩具车向当前行动方向前进或后退一定距离(如 10px),等待节点 Wait 则是停顿一段时间(如 1s),以模拟玩具车到达目的地的效果。

行为节点 Action 则表示停止当前的移动操作,该节点实现中,会将当前行动方向(direction)置为 0,从而停止所有的移动操作。

最后,我们在代码中通过 blackboard 对象来设置行为树的上下文信息,包括当前行动方向(direction)、玩具车当前位置(x)和目标位置(targetX)。在行为树运行时,首先会执行 MyBehaviorTree 类的构造函数,生成一条完整的行为树,然后调用 Composite.tick() 方法来执行该树,并根据子节点的执行结果,返回 success 或 failure。

总结

通过以上代码实例,我们可以看到,行为树在前端开发领域中有着广泛的应用场景和实现方法。无论是游戏编程、人工智能还是用户交互等领域,行为树都可以提供一种简洁高效的算法实现,优化程序运行效率,提高代码的可读性和可维护性。

另外,使用 behavior3ts 框架可以大大简化行为树的实现和调试过程,提高开发效率,减少出错的可能性。虽然 behavior3ts 的学习门槛较高,但一旦掌握了其中的设计思想和使用技巧,就可以轻松实现各种复杂的行为树结构和逻辑,为项目的开发和部署提供了强有力的支持。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/600572c881e8991b448e8f29

纠错
反馈