在实体组件系统引擎中,如何处理相关实体组?


47

在研究了几种游戏设计模式之后,我为我的游戏引擎选择了Entity-Component-System(ES System)。我正在阅读文章(主要是T = Machine)并查看一些源代码,我认为我已经足够入门。

我正在努力的只有一个基本想法。如何处理相互依赖的实体组?

让我举一个例子:

假设我正在制作一个标准的空中射击游戏(例如Jamestown),并且我想构造一个具有多个不同但相互连接的部分的“老板实体”。分解可能看起来像这样:

  • 船体:运动,渲染
  • 大炮:位置(相对于舰体锁定),向英雄追踪\开火,受到伤害直到被禁用
  • 核心:位置(相对于舰体锁定),向英雄追踪\射击,对伤害造成伤害直到被禁用,对舰组中的所有其他实体禁用(毁灭)

我的目标是将某些东西识别(并操纵)为独特的游戏元素,而不必每次我要构建新的聚合元素时都必须重写子系统。

如何在ES系统中实施这种设计?

  1. 我是否实现某种父子实体关系(实体可以有孩子)?这似乎与实体只是空容器的方法相矛盾,并使其感觉更面向对象。
  2. 我是否将它们实现为具有某些连接组件(BossComponent)和相关系统(BossSubSystem)的单独实体?我不禁认为这将很难实现,因为组件之间的通信方式似乎是一个巨大的陷阱。
  3. 我是否将它们实现为一个具有一组组件(ShipComponent,CannonComponents,CoreComponent)的实体?这似乎改变了ES System的意图(这里的组件似乎太像重量级的实体),但是我知道这一点,所以我想我会把它放在那儿。
  4. 我是否将它们实现为我提到的其他内容?

我知道在OOP中可以很容易地实现这一点,但是我选择坚持使用ES而不是OOP是我会坚持的。如果我需要打破纯粹的ES理论来实现此设计,我会(不像我以前没有折衷过纯粹的设计),但是出于性能原因,我宁愿这样做,而不是从糟糕的设计开始。

为了获得额外的荣誉,请考虑相同的设计,但是实际上每个“老板实体”都连接到由主体,主要核心和3个“老板实体”组成的更大的“ BigBoss实体”。这将使我看到至少3个维度的解决方案(祖父母-父母子女)...对我来说应该绰绰有余。


2
它只是连接到实体的不同网格物体组件,而连接到Boss实体的舰船和加农炮网格物体,却不会过于庞大。顺便说一句,实体组件系统是OOP!
Maik Semder

2
是的-这些T-Machine文章中最糟糕的是错误的想法,即某种程度上它不是面向对象的。实体的大多数组件系统都是完全面向对象的,而不是基于继承的。
Kylotan

3
我认为他们强调非OOP的本质,因为“思考经典的OOP”会给您带来很多麻烦。到目前为止,我已经帮助了一些人开始使用实体系统,这是最大的障碍。首先,尝试将代码放入组件中,尝试使组件相互继承,等等,这是一个巨大的问题,但是很高兴看到当这个想法最终被完全理解后,一切就开始了。
PSpeed 2012年

@MaikSemder我收拾了我的评论,然后将其移至聊天室
MichaelHouse

1
就像我理解@MaikSemder一样,在您引用的ES系统中,一个实体可以具有多个相同类型的组件,而负责这些组件的子系统必须处理这个事实?因此,一个实体可以具有多个渲染组件,而这些组件的数据和子系统将决定如何正确渲染它们?那会导致更少的实体,可能更少的组件,但更深层次的子系统逻辑,对吗?
约翰·丹尼尔斯

Answers:


41

如果我处于这种情况下,我将创建老板的每个部分作为一个单独的实体。这些“子实体”将包括某种AttachmentPointParentEntity组件。该组件将包括对上级实体的引用以及与上级位置的偏移。更新位置时,他们检查父位置并应用偏移量以生成自己的位置。此外,它可以进行检查以确保父实体仍然存在。此外,您可以具有一个SubEntity组件来跟踪父实体的子实体的存在。这样一来,您就可以做一些事情,例如仅在破坏带有防护罩的手臂时使老板的核心变得脆弱。

我目前TargetEntity在我的游戏中使用一个组件,该组件用于炮塔跟踪以及地精将何时拾取资源。它可以检查目标实体的位置并相应地更改其行为。没有位置的实体永远不会被添加为目标,因此那里没有后顾之忧。但是,当更深入地进行检查时,例如检查父子实体的健康状况,屏蔽,功率储备或其他任何内容,您必须确保父子实体确实具有相关组件。

通过使每个零件成为自己的实体,可以允许您向凸台的每个零件添加其他不同的零件,从而保持了实体/组件框架的灵活性。例如,凸台的一部分可能具有枪支组件和健康组件,而另一部分可能具有防护罩组件和健康组件。

我在这里找到了关于该主题的另一个讨论。用户在其中讨论将相同类型的多个组件添加到一个实体(这对我来说似乎是个坏主意)。这似乎是一次有用的对话,尽管我还没有阅读整个讨论。


这里有很多很好的信息。您已经很好地说明了解决方案,请给我一个例子,可能还要回答1或2个问题,以后再回头。链接的讨论似乎也很有趣,尤其是当我开始进行更困难的实现时。谢谢@ Byte56!
约翰·丹尼尔斯

约翰,没问题!当然,有很多不同的方法可以实现EC系统。我想这个答案的系统就是我在这个答案中描述的系统。祝您比赛顺利!
MichaelHouse

您的方法是最灵活的,可以在通才游戏引擎中使用它。
郊狼2012年

7

在不了解有关现有系统的太多细节的情况下,我对此建模的方式(一定程度上在我自己的实体系统中)是具有类似AttachedTo(parentEntity)的组件。然后可以为任何子级赋予AttachedTo(boss)组件。

然后,渲染系统(或任何其他系统)获取具有以下组件的实体:Position,AttachedTo等,并形成适当的层次结构。


这似乎是共识答案。下次,我将提供更多实施细节,以供人们参考。谢谢@PSpeed!
约翰·丹尼尔斯

4

如果您想要一个仅由ID表示的实体,则可以通过特殊组件来包含实体。您可以将其称为CompositeComponent,其中包含子实体ID的列表,以及用于从该列表添加/删除子项的接口。

显然,任何依赖于位置等的组件都需要与此组件配合才能正确放置实体。如何执行此操作将在某种程度上取决于您当前如何执行定位。

顺便说一句,没有“纯粹的ES理论”-从组件中制造实体是一种流行的方法,但是精确的方法尚未标准化。


是的,我应该学会在任何设计讨论中都不要使用“纯”一词……没有这种东西。ConpositeComponent路线似乎是这里的共识。谢谢@Kylotan!
约翰·丹尼尔斯
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.