基于组件/实体的设计+行为树=>如何集成?


9

在我当前的项目中,我实现了一个基于组件/实体的系统,基本上遵循了大多数最佳实践,但是这个未定义的领域却存在

因此,我得到了(略微扩展的)实体,它们基本上是一个intID,一个人类可读的名称,一个std::map组件和一个long“类型指示符”,用于显示存在哪些组件(我enum对所有组件有2的幂类型,并且每当将一个组件添加到Entity时,我都会通过按位操作自动更改该长度,比较此答案)。

然后是Components,也很简单:intID,enum作为组件类型,父Entity指针以及std::map该组件拥有的所有属性。

最后,一些处理实际逻辑处理的系统/管理器。他们首先检查当前处理的实体是否具有匹配的long“类型指示器” =该系统的所有必需组件都已存在。然后,如果需要,它将访问一些属性,并直接调用相应组件中的某些函数或发送一些消息(通过消息分发程序)。

底线:到目前为止,一个相当标准的事件驱动的基于组件/实体的系统与数据驱动的方法相结合(比较,组件没有硬编码的数据变量,而是作为(某些)组件的通用映射组件的/ archetypes将在以后从文件中读取,并且可以选择添加其他数据,这不是实际组件代码的一部分。

现在,我还要在该项目中引入“ 行为树”(基于AiGameDev BTSK),但是我不确定是否以及如何将它们链接到现有组件,或者通常如何集成这些设计。

我想到了几个相关的想法/观点/问题:

  1. 我的BT将再次从文件中读取。目前,我很难理解如何最好地BT Action在该树中的a和应用程序中的实际编码之间建立联系。是否应该在BT文件中使用的动作名称和指向实际逻辑实现的函数指针之间建立某种映射?解决该问题的通常方法是什么?

  2. 我假设我必须为所有不同Entity类型创建BT (因此,对于我多次提到的长“类型指示器”所指示的每种与游戏逻辑/人工智能相关的组件组合)。结果,将BT Action实现放入组件中没有意义,因为每个动作很可能会涉及许多组件,不是吗?

  3. 那么BT Action逻辑是否应该位于一个/多个单独的系统中(想法1的映射所指向的系统指向的方法)?然后,系统将根据我的long“类型指示器” Entity检查当前是否已检查BT并被告知执行特定操作(=系统中的方法)的BT(实际上具有必需的组件)。但是,如果不是这样(例如,因为BT创建者确实忽略了特定情况,即在运行时可能不再将必要的组件附加到Entity),则什么都不会发生。

问题:

  • 是否有经过验证的集成概念?
  • 您对我上面的三点有何看法?
  • 在我的基于组件/实体的设计方面,还有其他需要考虑的事情吗?

关于点1:行为树不过是主要用于创建角色行为的可视DSL。BehaviorTree组件不应执行比Script组件更多或更少的操作。要点3:在常规字段上使用地图的原因是什么?
埃里克

#1:在这种情况下,“ DSL”代表什么?#3:对不起,但是我不能跟随你。请仔细解释您的意思?
菲利普·奥尔加耶

1
可能是领域特定语言,即 用于处理非常具体问题的自定义语法。
Patrick Hughes

帕特里克(Patrick)是正确的,尽管语义也是其中的一部分,并且“非常”可能会从此定义中删除。-关于3:抱歉,它应该显示为:“ 在组件中的常规字段上使用映射的原因是什么?”
埃里克

关于3:我希望以后能够动态地指定C ++代码之外的其他属性(流行语:数据驱动)。为了简单起见,我(至少到目前为止)将所有属性(使用映射)放入此通用框架中,即使是那些已在代码中修复的属性,因此也可能是真正的C ++字段。如果这成为性能问题,则可能不得不稍后再讨论……
Philip Allgaier 2013年

Answers:


2

目前,我很难理解如何最好地在该树中的BT动作与应用程序中的实际编码之间建立联系。是否应该在BT文件中使用的动作名称和指向实际逻辑实现的函数指针之间建立某种映射?解决该问题的通常方法是什么?

忘记函数指针并考虑对象。理想情况下,行为树中的每个节点(从现在开始为BT)将与代码中的一个对象相对应。这些对象将具有标准接口,可让您将它们排列成树并进行遍历。一组函数指针适合该行为,但它根本无法捕获树的结构。

结果,将BT动作实现放入组件中是没有意义的,因为每个动作很可能会涉及许多组件,不是吗?

我希望实体具有单个BehaviorTree组件,该组件存储该实体的BT的相关数据。BT的执行由BT组件或BT子系统完成,具体取决于您在系统中处理组件的方式。与使用组件的几乎所有东西一样,他们将不得不引用其他组件来完成工作,但是那些其他组件将不必对BT有所了解。

在最简单的级别,可用的不同操作将被编码到各种BT节点对象中。他们应能够通过根据需要操纵组件来使相关实体发挥作用,例如。访问移动组件以移动。


第1段:是的,BT本身就是一个对象(就像我说的那样,就像AiGameDev的版本一样)。我只是在考虑动作本身的函子,但是您的第2段改变了这一点。由于某种原因,这种真正简单的方法从未出现在我身上(实体拥有自己的BT成员实例)。可能是由于使用了全新的组件,所以我不再觉得简单而简单了,所以我一直在寻找一种将组件与BT东西混合的方法,但实际上并不需要。
菲利普·奥尔加耶

我之前迷失的主要事情是如何将动作与实体联系起来。现在很清楚:动作通过其树知道哪个实体,而树又知道它属于哪个实体。
菲利普·奥尔加耶

@Philip Allgaier我很好奇,您最终是如何创建BT节点的?您是否将其创建为1个行为节点= 1个实体(每个1个游戏对象会有很多实体),还是将节点创建为普通类(与ECS不相关),还是使用其他方法?谢谢!
cppBeginner '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.