javascript - 我应该如何在所有蜱虫触发的行为树的所有执行之间共享状态?

标签 javascript typescript data-structures behavior behavior-tree

我仍在学习Behavior Tress,我对“黑板”的理解本质上是一个状态对象。当通过蜱虫将状态对象传递给函数调用(节点和叶子)时,我应该如何在所有先前蜱虫触发的树的所有执行之间共享状态?

我最初认为状态应该是不可变的,以便函数可以是“纯粹的”。但是,如果状态是不可变的,则意味着无论执行过程中出现的后续滴答具有不同的状态值,前一次滴答触发的任何后果都必须完整执行。

例如,如果行为树是这样的: enter image description here

何时 Tick_1刚进来的时候状态是这样的:

{ 
  user: { cash: 10 }
}

所以,在Tick_1 ,用户有 10 美元并且有足够的现金购买牛奶。行为树将沿着步行到商店然后购买牛奶的路径进行。

但是,“步行去商店”操作是异步的,需要一些时间才能执行“购买牛奶”操作。现在,当来自 Tick_1 的“步行到商店”操作时仍在发生,再次勾选 Tick_2此时出现的状态是用户口袋里现在有 0 美元:

{ 
  user: { cash: 0 }
}

基于 Tick_2 的最新状态用户没有更多的钱可能是由于Tick_2期间发生的事情造成的。但因为之前执行的树来自Tick_1仍在进行中,并且不了解新状态,因为它的状态副本是旧状态,并且它们不共享共同的可变状态,它最终会在真正应该执行“购买牛奶”操作时继续执行“购买牛奶”操作不是因为此时用户已经没有现金了!

在我看来,如果传递给刻度的状态是不可变的单独状态副本,则必须完成之前做出的决定,并且我们不能“取消”之前的决定或执行。

但是,如果我们使用共享状态,则这意味着状态是可变的,并且任何函数或操作都可以通过任何副作用来更改它们。由于太多地方改变共同状态,它可能会变得非常困惑且难以维护。

我的问题是:

  • 应该如何构建行为树的黑板或状态?状态应该是可变的还是不可变的?
  • 每个记号是否应该共享一个公共(public)的状态副本,以便前一个记号的树的执行能够了解状态中的最新值,以便它们停止继续或做出不同的 react ?
    • 如果是这样,应该如何优雅地完成?

在我的例子中,我使用的是 Typescript,但我假设(?)这个概念在任何其他上下文和语言中都应该类似。

PS:我想我可以交换条件的位置并“步行到商店”来减少示例中的问题,但我试图用它来说明我遇到的困境。

最佳答案

如果支持并行节点,黑板需要是可变的和线程安全的。您是正确的,在您的示例中,一个异步节点更改了 cash 的值,而第二次遍历认为它有足够的现金来执行某些操作,这可能是一个问题。

您可以为每个刻度传递一个指向黑板的引用或指针到每个节点,或者在创建节点期间,给它们一个指向黑板的引用/指针。这两种方法都是有效的,但无论如何,节点不应该拥有黑板或其中的值的副本。这会造成浪费,并且试图保持黑板副本的连贯性会增加大量开销。

还有其他事情需要考虑。你提到了

But because the previous execution of the tree from Tick_1 is still in progress ... it will eventually go on and perform the "Buy Milk" action when it really shouldn't because by this time, the user has no more cash!

这并不完全正确。 Tick_1 勾选异步节点后,会立即返回“Running”状态,序列向上传递到根。因此,Tick_1Tick_2 出现之前完成,但是“走到商店”节点在其他线程上仍然处于事件状态。

在您的示例中,我认为这不会成为问题。该序列不会继续到“买牛奶”节点,直到所有先前的节点都成功(即未失败且未运行)。

如果您有一个更复杂的树,其中来自完全不同分支的节点正在异步运行,并且还可能修改 cash,则必须在执行操作节点之前以原子方式检查前置条件。即“买牛奶”节点被替换为子树,该子树测试代理是否有足够的现金,然后去购买牛奶。

关于javascript - 我应该如何在所有蜱虫触发的行为树的所有执行之间共享状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72323441/

相关文章:

javascript - 在对象中创建键时如何避免 if else ?

javascript - View 没有更新,而是类变量的值在 Angular 2 beta 中发生了变化

angular - 在 Angular2 rc4 中对输入类型 = 日期使用自定义 ControlValueAccessor 时出现格式错误

typescript - Aurelia Typescript 项目仅适用于 Chrome

c - C中链表内部的结构

c# - 拆分两组

javascript - Android:如何在点击时启动系统放大镜

javascript - Bootstrap 轮播在第一张图片上向左滑动消失

javascript - 为什么函数返回的数据不在 react 中呈现?

data-structures - 如何在不相交的集合数据结构中创建集合并解决并集?