Зарегистрировать компоненты игровых объектов в игровых подсистемах? (Компонентный дизайн игровых объектов)

Я создаю систему объектных игровых объектов. Несколько советов:

  1. GameObject это просто список Components,
  2. Есть GameSubsystems, Например, рендеринг, физика и т. Д. Каждый GameSubsystem содержит указатели на некоторые из Components, GameSubsystem это очень мощная и гибкая абстракция: она представляет любой фрагмент (или аспект) игрового мира.

Существует необходимость в механизме регистрации Components в GameSubsystems (когда GameObject создан и составлен). Есть 4 подхода:


  • 1: Схема цепочки ответственности. каждый Component предлагается каждому GameSubsystem, GameSubsystem принимает решение, которое Components зарегистрироваться (и как их организовать). Например, GameSubsystemRender может зарегистрировать Renderable Components.

профи. Components ничего не знаю о том, как они используются. Низкая связь. А. Мы можем добавить новый GameSubsystem, Например, давайте добавим GameSubsystemTitles, который регистрирует все ComponentTitle и гарантирует, что каждый заголовок уникален и предоставляет интерфейс для запроса объектов по заголовку. Конечно, ComponentTitle не должен быть переписан или унаследован в этом случае. B. Мы можем реорганизовать существующие GameSubsystems, Например, GameSubsystemAudio, GameSubsystemRender, GameSubsystemParticleEmmiter могут быть объединены в GameSubsystemSpatial (чтобы разместить все аудио, emmiter, render Components в той же иерархии и использовать родительские относительные преобразования).

против. Индивидуальная проверка. Очень неэффективно.

против. Subsystems знать о Components,


  • 2: каждый Subsystem ищет Components конкретных типов.

профи. Лучшая производительность, чем в Approach 1,

против. Subsystems до сих пор знаю о Components,


  • 3: Component регистрируется в GameSubsystem(s), Во время компиляции мы знаем, что существует GameSubsystemRenderer, поэтому давайте ComponentImageRender будет вызывать что-то вроде GameSubsystemRenderer::register(ComponentRenderBase*).
    Наблюдатель шаблон. Component подписывается на событие "обновление" (отправлено GameSubsystem(s)).

профи. Спектакль. Нет ненужных проверок, как в Approach 1 а также Approach 2,

против. Components плохо связаны с GameSubsystems,


  • 4: образец посредника. GameState (который содержит GameSubsystems) может реализовать registerComponent(Component*).

профи. Components а также GameSubystems ничего не знаю друг о друге.

против. В C++ это выглядело бы как уродливый и медленный переключатель типа.


Вопросы: Какой подход лучше и чаще всего используется в компонентном проектировании? О чем говорит практика? Любые предложения по (управляемой данными) реализации Approach 4?

Спасибо.

2 ответа

Решение

Голосуйте за третий подход.

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

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

  • Управляемый данными дизайн более применим. В идеале, таким образом, вы можете спроектировать систему, в которой компоненты полностью определены в терминах данных, но не в C++.


РЕДАКТИРОВАТЬ: Одна функция, о которой я думал, работая над CBGOS. Иногда удобно иметь возможность проектировать и конструировать пассивные компоненты без подсистем. Когда вы думаете об этом, четвертый подход - единственный путь.

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

Таким образом, если объект должен быть удален из механизма, одно сообщение, содержащее идентификатор объекта, может быть отправлено каждой подсистеме. Затем прокси-сервер может быть удален из каждой коллекции подсистем независимо.

Другие вопросы по тегам