В Entity-Component-System Engine, как мне работать с группами зависимых объектов?

48

Пройдя несколько шаблонов игрового дизайна, я выбрал Entity-Component-System (ES System) для моего игрового движка. Я читаю статьи (в основном T = Machine ) и рассматриваю некоторый исходный код, и я думаю, что получил достаточно, чтобы начать.

Есть только одна основная идея, с которой я борюсь. Как мне работать с группами объектов, которые зависят друг от друга?

Позвольте мне использовать пример:

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

  • Тело корабля: движение, рендеринг
  • Пушка: Положение (заблокировано относительно корпуса корабля), Отслеживание \ Огонь у героя, Получение урона до отключения
  • Ядро: Положение (заблокировано относительно корпуса корабля), Отслеживание \ Огонь героя, Получение урона до отключения, Отключение (э-э ... уничтожение) всех других объектов в группе корабля.

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

Как мне реализовать этот вид дизайна в ES System?

  1. Реализую ли я какие-то отношения сущности родитель-потомок (сущности могут иметь детей)? Это, кажется, противоречит методологии, согласно которой сущности являются просто пустым контейнером, и заставляет их чувствовать себя более ООП.
  2. Реализую ли я их как отдельные сущности, с каким-то связующим компонентом (BossComponent) и связанной системой (BossSubSystem)? Я не могу не думать, что это будет сложно реализовать, поскольку взаимодействие компонентов кажется большой медвежьей ловушкой.
  3. Реализую ли я их как один объект с набором компонентов (ShipComponent, CannonComponents, CoreComponent)? Похоже, что это отклоняется от намерения системы ES (компоненты здесь кажутся слишком похожими на объекты с большим весом), но я знаю об этом, поэтому я решил, что я это изложу.
  4. Я реализую их как что-то еще, что я упомянул?

Я знаю, что это очень легко реализовать в ООП, но я остановлюсь на выборе ES вместо ООП. Если мне потребуется порвать с чистой теорией ES для реализации этого дизайна, я сделаю это (не то чтобы раньше мне не приходилось ставить под угрозу чистый дизайн), но я бы предпочел сделать это по соображениям производительности, а не начинать с плохого дизайна.

Для дополнительного кредита, подумайте о том же дизайне, но каждая из «сущностей босса» фактически была связана с более крупной «сущностью BigBoss», состоящей из основного корпуса, основного ядра и 3 «боссовых сущностей». Это позволило бы мне увидеть решение по крайней мере для 3 измерений (дедушка-родитель-ребенок) ... которого должно быть более чем достаточно для меня.

Джон Дэниелс
источник
2
Это просто различные компоненты сетки, прикрепленные к сущности, сетка корабля и пушки, прикрепленная к сущности босса, не слишком излишняя. Кстати, система компонентов сущности ООП!
Майк Земдер
2
Да - худшая часть этих статей T-Machine - ошибочная идея, что это как-то не объектно-ориентировано. Большинство систем компонентов для сущностей полностью объектно-ориентированы, но не основаны на наследовании.
Kylotan
3
Я думаю, что они подчеркивают не-ООП природу, потому что «мышление классического ООП» доставит вам столько неприятностей. Я уже помог нескольким людям начать работу с системами сущностей, и это самое большое препятствие. Попытка поместить код в компоненты, попытаться создать компоненты, которые подклассируют друг друга и т. Д., Поначалу представляет собой огромную проблему, но приятно видеть, что свет появляется, когда идея наконец-то полностью осознана.
PSpeed
@MaikSemder Я убрал свои комментарии и переместил их в чат
MichaelHouse
1
Я так понимаю, @MaikSemder. В системе ES, на которую вы ссылаетесь, у сущности может быть несколько компонентов одного типа, и подсистема, отвечающая за эти компоненты, должна будет справиться с этим фактом? Таким образом, у сущности может быть несколько компонентов рендеринга, и данные и подсистемы этих компонентов будут определять, как правильно их визуализировать? Это привело бы к меньшему количеству объектов, потенциально меньшему количеству компонентов, но немного более глубокой логике подсистемы, правильно?
Джон Дэниелс

Ответы:

42

Если бы я был в такой ситуации, я бы создал каждую часть босса как отдельную сущность. Эти «суб-сущности» будут включать в себя некоторый вид AttachmentPointили ParentEntityкомпонент. Этот компонент будет включать ссылку на родительскую сущность и смещение от родительской позиции. При обновлении позиции они проверяют родительскую позицию и применяют смещение для создания своей собственной позиции. Кроме того, он может выполнять проверки, чтобы гарантировать, что родительский объект все еще существует. Кроме того, вы можете иметь SubEntityкомпонент, который отслеживает существование дочерних объектов для родительского объекта. Это позволяет вам делать такие вещи, как только сделать ядро ​​босса уязвимым, когда оружие со щитами уничтожено.

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

Делая каждую часть своей собственной сущностью, вы поддерживаете гибкость структуры сущности / компонента, позволяя вам добавлять дополнительные и разные компоненты к каждой части начальника. Например, одна часть босса может иметь компонент оружия и компонент здоровья, а другая - компонент щита и компонент здоровья.

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

MichaelHouse
источник
Здесь много полезной информации. Вы хорошо объяснили решение, приведите мне пример и, возможно, ответьте на еще 1 или 2 вопроса, на которые мне пришлось бы вернуться позже. Связанное обсуждение также кажется интригующим, особенно когда я начинаю углубляться в реализацию. Спасибо @ Byte56!
Джон Дэниелс
Нет проблем, Джон! Конечно, существует много разных способов реализации системы EC. Система, которую я имел в виду для этого ответа, является той, которую я описал в этом ответе . Удачи в вашей игре!
MichaelHouse
Ваш подход является наиболее гибким и разумно использовать его в универсальном игровом движке.
Койот
7

Не зная слишком много подробностей о ваших существующих системах, я бы смоделировал это (и в некоторой степени в своей собственной системе сущностей), чтобы иметь такой компонент, как AttachedTo (parentEntity). Любому из потомков может быть присвоен компонент AttachedTo (boss).

Затем система рендеринга (или что-то еще) захватывает объекты с компонентами: Position, AttachedTo и т. Д. И формирует правильные иерархии.

PSpeed
источник
Похоже, это единодушный ответ. В следующий раз я дам больше деталей реализации, чтобы люди могли пережевать. Спасибо @PSpeed!
Джон Дэниелс
4

Если вы хотите, чтобы сущность была представлена ​​только идентификатором, то удержание сущностей может быть сделано через специальный компонент. Вы можете назвать его CompositeComponent, и он содержит список идентификаторов дочерних объектов и интерфейсы для добавления / удаления дочерних элементов из этого списка.

Очевидно, что любые компоненты, которые зависят от положения и т. Д., Должны будут работать с этим, чтобы правильно разместить объект. Как это реализовать, будет зависеть от того, как вы реализуете позиционирование в настоящее время.

Между прочим, не существует «чистой теории ES» - создание сущностей из компонентов является популярным подходом, но точный метод еще не стандартизирован.

Kylotan
источник
Да, я должен научиться не использовать слово «чистый» в любом обсуждении дизайна ... ничего такого. Маршрут ConpositeComponent представляется здесь консенсусом. Спасибо @Kylotan!
Джон Дэниелс