Как организовать сущности в модели ECS? - PullRequest
1 голос
/ 04 февраля 2020

У меня есть система рендеринга, которая перебирает все компоненты MeshDrawData, пакетирует и рисует их. Моя реализация ECS допускает только один тип компонента для каждой сущности.

Теперь я хочу представить падг "Player". Мой OOP склад ума говорит так:

Pseudocode:
auto e = createEntity();
createSpriteComponent(e,...); // this creates a MeshDrawData internally for e entity.
createColliderComponent(e,...);

Это работает нормально, НО, скажем, теперь я тоже хочу отрисовать линию. Если я сделаю это:

Pseudocode:
auto e = createEntity();
createSpriteComponent(e,...); // this creates a MeshDrawData internally for the e entity.
createColliderComponent(e,...);
createLineComponent(e,...); // this creates a MeshDrawData internally for the e entity

Здесь вы можете увидеть проблему .. Я создал два компонента MeshDrawData для сущности e ..

Учитывая мой нереальный фон движка, я создаю актера и добавить компоненты к нему. Я всегда думал, что в ECS сущность похожа на актера, но я вижу, что я совершенно неправ.

Как вы организуете свои сущности, чтобы, например, разрешить варианты использования, подобные той, которую я упоминал ранее? Что именно должен представлять субъект?

Возможные решения:

  1. Никогда не создавайте объект с SpriteComponent и LineComponent, которые создают один и тот же MeshDrawData в том же объекте .. (очевидно, но подвержен ошибкам) ​​
  2. Создайте дочернюю сущность для каждого SpriteComponent и / или LineComponent и добавьте ее к соответствующему дочернему элементу. Это будет работать, но это сделает длинные деревья иерархии сущностей ... не уверен, что это более подвержено ошибкам. ...

1 Ответ

1 голос
/ 09 февраля 2020

1:1 Entity:Component - скучное ограничение, но также хорошее ограничение для большинства двигателей ECS.

Чтобы устранить проблемы, я обычно делаю одно из следующих действий: -

  1. Запретить это по умолчанию :: Движок игры выдает assert-fail во втором случае.

  2. Добавьте проверку , например, в createLineComponent, существует ли MeshDrawData, и выполните некоторые пользовательские действия.

    В основном я делаю это следующим образом: -

    void createLineComponent(Entity e){
        auto meshComponent=engine->addJustInCase<MeshDrawData>(e);
        //^ if the component exists - just request the component, if not, create it
        meshComponent->setFormat ...
    }
    
  3. Разделить сущность и добавить отношение один-ко-многим :: Подходит для слишком сложного объекта.

    3.1 Проще говоря - дочерний объект (ы) родительского кэша в качестве его (их) полей.

    3.2 Полная система для определенного отношения 1: N.
    Дочерняя система отношений должна быть очень конкретизированной c in тип
    например 1:N Collider-Sprite, а не 1:N entity-entity.

В своей игре я смешиваю их около 60:30:10 (9: 1). Это работает хорошо.
Если это начинает становиться беспорядком - используйте фабричный образец, чтобы инкапсулировать это.

Если у кого-то есть идеи (лучше), пожалуйста, ответьте. Я бы тоже хотел это услышать.

...