Entity Component System - Как реализовать преобразование объекта?

11

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

Во-первых, позвольте мне прояснить немного терминологии, которую я собираюсь использовать в этом вопросе:

  • Я называю « Компонент » структурой данных, которая хранит соответствующие данные для конкретной системы.
  • Я называю « Системой » совокупность методов и структур данных, которая использует Компоненты для обновления состояния игры / интерфейса с пользователем.
  • « Сущность » - это, в основном, просто идентификатор, используемый для извлечения определенных компонентов и изменения их данных в игровой логике.

Каждая система владеет (ID-сопоставленным) массивом своего типа Компонента (например, Physics-> PhysicsComponent, AI-> AIComponent, Rendering-> RenderingComponent), чтобы она могла эффективно выполнять итерации по данным.

Однако не все компоненты являются собственностью системы. Например, компонент Transform хранит положение объекта, вращение и масштаб. Это одна из самых важных частей сущности (даже Unity делает ее обязательной), поскольку она используется многими системами, например, физикой, искусственным интеллектом, рендерингом и т. Д.

Это в значительной степени проблема, с которой я сталкиваюсь. Поскольку Transform используется во многих других системах, как мне найти одну из них для каждого компонента? Одно возможное решение, которое я вижу, - заставить каждый компонент хранить свой собственный идентификатор объекта. Было бы легко получить любой компонент, подобный этому, но он не был бы настолько эффективным, и это также противоречило бы концепции Компонента как изолированного и независимого пакета данных, который не знает ни о каком другом.

Есть ли правильный способ решить эту проблему? Должен ли Transform быть даже компонентом?

CRefice
источник
3
+1 за «Во-первых, позвольте мне прояснить немного терминологии, которую я собираюсь использовать в этом вопросе:»
Vaillancourt
Я хотел бы видеть этот тип вопросов больше на этом сайте. +1
С. Тарык Четин
Просто сохраните все компоненты как глобальные переменные
Miles Rout

Ответы:

2

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

Ваша физика и системы рендеринга, безусловно, потребуют преобразования, однако система ИИ не будет. Следовательно, имеет смысл инкапсулировать преобразование в свой собственный класс компонентов. Все такие заинтересованные системы будут использовать одни и те же данные, поэтому для сущности имеет смысл иметь указатель на объект преобразования или идентификатор для объекта преобразования, хранящегося в другом месте.

Если вы выберете последнее решение, то каждой системе, которая заинтересована в преобразовании, потребуется доступ туда, где хранится объект преобразования.

Если вы выберете первое, то все, что нужно каждой системе - это получить доступ к самому объекту и запросить преобразование.

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

В последнем случае таких проблем нет, но требуется изменить дизайн объекта сущности для хранения указателей на объекты, а не идентификаторов компонентов.

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

Посмотрите на этот обзор ECS для получения дополнительной информации об этом.

В конце концов, вам решать, что для вас важнее: простота разработки или производительность.

Наконец, я хотел бы отметить, что ваш вопрос является отличным примером вопросов дизайна, о которых думают сторонники ECS, и что нет окончательного решения «серебряной пули».

Ян Янг
источник
Спасибо за ваши предложения. У меня есть вопрос: почему системе ИИ не нужна позиция объекта?
CRefice
Вы путаете положение (вектор из 3-х чисел) с трансляцией (матрица преобразования, построенная из вектора положения). Матрица преобразования строится из преобразований перемещения, поворота и масштаба. Это гораздо больше информации, чем требуется системе ИИ, хотя вы, конечно, можете извлечь из нее вектор положения. Лично я бы выделил положение, ориентацию и размеры в их собственный компонент и использовал их для создания и обновления Transform.
Ян Янг
@IanYoung Разделение их может принести больше вреда, чем пользы, потенциально, если вы обнаружите, что вам нужно положение и ориентация вместе чаще, чем вы делаете положение или ориентацию по отдельности. В этом случае размещение атрибутов данных положения и ориентации в одном компоненте может повысить производительность кэша.
Нарос
1
Я предпочитаю объединять все три: положение, ориентацию и масштаб в один компонент, и в тех случаях, когда конкретному подсистеме требуется только позиция или ориентация, я бы рекомендовал дублировать данные и синхронизировать их в четко определенных точках игрового цикла. ,
Нарос
@Naros да, это то, что я имел в виду: два компонента, преобразование и (в моей структуре) SpatialData, которые содержат положение, скорость, ориентацию и угловую скорость. Положение и ориентация используются для создания и обновления Transform.
Ян Янг