Идентификация типов объектов в системе компонентов

10

Если у сущности нет явного «типа» (например, плеера) и это просто набор компонентов, как мне определить сущности, над которыми мои системы должны и не должны работать? Например, в игре в понг весло и мяч сталкиваются с границами окна. Однако системы обработки столкновений для каждого из них будут разными, поэтому система не должна обрабатывать объекты неправильного типа.

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, в таком случае сущность больше не является просто набором компонентов?

Garee
источник

Ответы:

21

Никол Болас отвечает прямо, но отходит в сторону и смотрит на вашу проблему на расстоянии: вам действительно не нужен тип сущности.

Вам нужно только позаботиться о том, «есть ли у объекта компонент X» или нет, и ваша проблема в том, что вы не определили его должным образом X. Если два объекта ведут себя по-разному, тогда присвойте им разные компоненты или просто установите логический флаг на компонент, если он заставляет его вести себя по-разному для разных конфигураций объекта. Используйте систему компонентов для принятия решений о поведении, а не о «типе» сущности. В этом весь смысл использования компонентов.

Вам полностью разрешено иметь PaddlePhysicsкомпонент / систему и отдельный BallPhysicsкомпонент / систему, если они ведут себя по-разному. Или вы можете разбить компоненты на более детализированные части, чтобы у вас был Bounceкомпонент, который есть только у Ball, и StopAtBoundaryкомпонент, который есть Ballи Paddleесть, если часть поведения достаточно сложна, чтобы оправдать совместное использование кода. Или вы можете просто создать PongPhysicsкомпонент с логическим флагом, Bouncesустановленным trueдля Ballи falseдля Paddle. Вы даже можете создать базовый WallCollisionкомпонент, а затем получить этот компонент, чтобы получить объект, BallWallCollisionкоторый добавляет дополнительное поведение, необходимое для этого.

Шон Миддледич
источник
4
Я думаю, что это должен быть принятый ответ, так как нет абсолютно никаких ограничений или проблем с «ванильной» ECS. Пометка объектов может быть легко достигнута путем создания выделенных компонентов, которые служат маркерами. Это также может быть просто фиктивный PlayerTypeComponent, который не делает ничего полезного, а просто служит тегом.
Тигучи
19

Система полезна, только если она полезна. Если система , в которой сущность является «просто набор компонентов» менее полезна , чем система , когда предприятие находится в основном является «собирающим компонентов», то сделать это .

Перестаньте пытаться делать «чистые» системы и сосредоточьтесь на создании хороших , которые делают то, что вам нужно. Используйте компоненты, пока компоненты больше не будут полезны для вас. Тогда используйте что-то еще.

Вы уже потратили больше времени на обдумывание, чем оно того заслуживает.

Николь Болас
источник
очень приятно +1 «Вы уже потратили больше времени на размышления об этом, чем это заслуживает»
Уэс
8
Я не думаю, что это вообще ответ. Тема усовершенствования ECS заслуживает значительного внимания, и Гэри (когда он опубликовал это в 2013 году), вероятно, не потратил достаточно времени на размышления об этом. Понятие, что тема не заслуживает больше времени, подразумевает, что системы должны быть простыми или тривиальными и, как правило, не заслуживающими нашего времени. Я предпочел бы ответ Шона Миддледича, поскольку он фактически пытается ответить на вопрос, а не отклонить его.
Гэвин Уильямс
Отличный ответ. Мне иногда приходится говорить это себе. Сосредоточиться на движении вперед.
Доминик Бу-Самра
5

Если вы хотите дать сущностям явный тип, самый простой способ - определить переменную типа в классе сущностей. Сохраняйте шаблон ЕС только до тех пор, пока он полезен.

В противном случае тип подразумевается через атрибуты компонента. Например, физический компонент будет иметь атрибут «мобильный против стационарного». Затем система знает, когда сталкиваются два мобильных устройства (мяч и весло). Точно так же вы можете иметь атрибуты того, как должна реагировать система столкновений. Просто остановить объект или отразить его? Просмотр атрибутов должен дать вам представление о том, что такое сущность, но это не имеет значения. Системам не нужно знать, с каким типом сущности они работают, им нужно предоставлять достаточно информации, используя предоставленные им компоненты.

Наконец, можно добавить дополнительный компонент, который содержит тип, но, как и при добавлении типа к сущности, вы в конечном итоге будете писать много кода, специфичного для типа, что противоречит цели системы EC.

MichaelHouse
источник
0

Сущность - это набор компонентов. Вы не можете назначить аккуратные метки случайному набору. Отказ от ограничений типа - цена за большую гибкость.

Конечно, вы можете иметь специальные (типизированные) классы сущностей, которые накладывают ограничения на компоненты.

В идеале компоненты являются независимыми. Таким образом, решением вашей проблемы было бы вызвать обработку коллизий для каждого подкомпонента по порядку. В реальных приложениях существуют взаимозависимости и проблемы с заказами. Если это так, вам нужна некоторая логика диспетчера в каждом методе класса Entity.

Карл
источник