识别实体组件系统中的实体“类型”


10

如果实体没有显式的“类型”(例如播放器),而仅仅是组件的集合,那么我如何识别系统应该和不应该使用的实体?例如,在Pong游戏中,桨和球都与窗口边界碰撞。但是,每个碰撞处理系统将有所不同,因此系统不应处理错误类型的实体。

void PlayerCollisionSystem::update(std::vector<Entity *> entities) {
  typedef std::vector<Entity *>::iterator EIter;
  for (EIter i = entities.begin(); i != entities.end(); ++i) {
    Entity *player = *i; // How do I verify that the entity is a player?

    // Get relevant components.
    PositionComponent *position = player->getComponent<PositionComponent>();
    VelocityComponent *velocity = player->getComponent<VelocityComponent>();
    SpriteComponent *sprite = player->getComponent<SpriteComponent>();

    // Detect and handle player collisions using the components.
  }
}

运动员和球都共享相同的相关组件类型以进行碰撞处理,但是它们的系统实现将有所不同。

如果我有一个包含所有游戏实体的容器,如何在不继承Entity或不包含诸如的成员变量的std::string type情况下识别特定类型的实体,在这种情况下,实体不再仅仅是组件的集合?

Answers:


21

尼科尔·波拉斯(Nicol Bolas)的回答直截了当,但退而求其次地并从远处看待您的问题:您确实不需要实体的类型。

您只需要关心“对象是否具有组件X”,问题就在于您没有正确识别X。如果两个对象的行为不同,则为它们提供不同的组件,或者仅在组件上放置一个布尔标志,以使其对于不同的对象配置具有不同的行为。使用组件系统来决定行为,而不是实体“类型”。这就是使用组件的全部要点。

如果它们的行为不同,则完全允许您拥有一个PaddlePhysics组件/系统和一个单独的BallPhysics组件/系统。或者,您可以将组件分解为更细的部分,从而使您拥有一个Bounce只有Ball拥有的StopAtBoundary组件,以及一个既拥有一部分BallPaddle拥有一部分的组件(如果部分行为足够复杂,以至于无法共享代码)。或者你也可以做一个PongPhysics具有布尔标志组件Bounces设置trueBallfalsePaddle。您甚至可以制作一个基本WallCollision组件,然后派生该组件以获取BallWallCollision,从而增加那里所需的额外行为。


4
我认为这应该是可以接受的答案,因为“香草” ECS绝对没有约束或问题。通过创建用作标记的专用组件可以轻松完成标记实体。它也可能只是一个虚假的PlayerTypeComponent,它没有做任何有用的事情,只是充当了标签。
tiguchi 2014年

19

系统仅在有用时才有用。如果实体“仅是组件的集合”的系统不如实体主要是“组件的集合” 的系统有用,那么请这样做

停止尝试制作“纯粹的”系统,而专注于制作能够满足您需求的优秀系统。使用组件,直到组件不再对您有用为止。然后再使用其他东西。

您已经花了更多的时间思考这个问题。


非常好+1“您已经花了更多的时间思考这个问题,不应该得到它”
2013年

8
我根本不认为这是一个答案,完善ECS的主题值得我们高度关注,而Garee(在他于2013年发布此主题时)可能没有花足够的时间来思考它。主题不值得花更多时间的概念意味着系统应该简单或琐碎,通常不值得我们花费时间。我更希望肖恩·米德迪奇(Sean Middleditch)的回答,因为它实际上是在尝试回答问题而不是不予理miss。
加文·威廉姆斯

好答案。我发现自己不得不偶尔对自己说这句话。专注于前进。
多米尼克·布·萨姆拉

5

如果要为实体提供显式类型,最简单的方法是在实体类中定义类型变量。只要有用,就保持EC模式。

否则,通过组件属性隐含类型。例如,物理组件将具有移动与固定属性。然后,系统知道两个手机(球和桨)发生碰撞的时间。同样,您可以具有碰撞系统应如何响应的属性。只是停止物体还是反射物体?查看属性应该使您了解实体是什么,但是应该无关紧要。系统不需要知道所使用的实体类型是什么,应该使用提供给它们的组件为它们提供足够的信息。

最后,可以添加一个包含类型的附加组件,但是,就像向实体添加类型一样,您最终将编写大量特定于类型的代码,从而违反了EC系统的目的。


0

实体是一组组件。您不能将整洁的标签分配给随机集。放弃类型约束是灵活性的代价。

当然,您可以具有特殊的(类型化的)实体类,它们对组件施加了限制。

理想情况下,组件是独立的。因此,解决问题的方法是按顺序在每个子组件上调用冲突处理。在实际应用中,存在相互依赖性和排序问题。如果是这种情况,则在Entity类的每个方法中都需要一些“分派器”逻辑。

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.