При проектировании системы компонент-сущность для моего движка я столкнулся с небольшим затруднением при хранении и извлечении компонента определенного типа.
Во-первых, позвольте мне прояснить немного терминологии, которую я собираюсь использовать в этом вопросе:
- Я называю « Компонент » структурой данных, которая хранит соответствующие данные для конкретной системы.
- Я называю « Системой » совокупность методов и структур данных, которая использует Компоненты для обновления состояния игры / интерфейса с пользователем.
- « Сущность » - это, в основном, просто идентификатор, используемый для извлечения определенных компонентов и изменения их данных в игровой логике.
Каждая система владеет (ID-сопоставленным) массивом своего типа Компонента (например, Physics-> PhysicsComponent, AI-> AIComponent, Rendering-> RenderingComponent), чтобы она могла эффективно выполнять итерации по данным.
Однако не все компоненты являются собственностью системы. Например, компонент Transform хранит положение объекта, вращение и масштаб. Это одна из самых важных частей сущности (даже Unity делает ее обязательной), поскольку она используется многими системами, например, физикой, искусственным интеллектом, рендерингом и т. Д.
Это в значительной степени проблема, с которой я сталкиваюсь. Поскольку Transform используется во многих других системах, как мне найти одну из них для каждого компонента? Одно возможное решение, которое я вижу, - заставить каждый компонент хранить свой собственный идентификатор объекта. Было бы легко получить любой компонент, подобный этому, но он не был бы настолько эффективным, и это также противоречило бы концепции Компонента как изолированного и независимого пакета данных, который не знает ни о каком другом.
Есть ли правильный способ решить эту проблему? Должен ли Transform быть даже компонентом?
источник
Ответы:
Это довольно широкий вопрос, ответ на который сильно зависит от вашей архитектуры. Однако я постараюсь дать вам общий ответ.
Ваша физика и системы рендеринга, безусловно, потребуют преобразования, однако система ИИ не будет. Следовательно, имеет смысл инкапсулировать преобразование в свой собственный класс компонентов. Все такие заинтересованные системы будут использовать одни и те же данные, поэтому для сущности имеет смысл иметь указатель на объект преобразования или идентификатор для объекта преобразования, хранящегося в другом месте.
Если вы выберете последнее решение, то каждой системе, которая заинтересована в преобразовании, потребуется доступ туда, где хранится объект преобразования.
Если вы выберете первое, то все, что нужно каждой системе - это получить доступ к самому объекту и запросить преобразование.
В первом случае проблема заключается в том, как предоставить доступ к хранилищу для преобразований каждой системе, не нарушая правил ООП, если вы заботитесь о таких вещах.
В последнем случае таких проблем нет, но требуется изменить дизайн объекта сущности для хранения указателей на объекты, а не идентификаторов компонентов.
Мое личное предпочтение состоит в том, чтобы спроектировать класс сущности для хранения указателей на составные объекты, поскольку это упрощает многие проблемы проектирования. Таким образом, каждая система, которая требует преобразования, может запросить его у объекта и игнорировать его, если это не так. Тем не менее, это несет вычислительные издержки, присущие указателям, то есть затраты на кэш-память.
Посмотрите на этот обзор ECS для получения дополнительной информации об этом.
В конце концов, вам решать, что для вас важнее: простота разработки или производительность.
Наконец, я хотел бы отметить, что ваш вопрос является отличным примером вопросов дизайна, о которых думают сторонники ECS, и что нет окончательного решения «серебряной пули».
источник