Для 2D-игры, которую я делаю (для Android), я использую компонентную систему, в которой GameObject содержит несколько объектов GameComponent. GameComponents могут быть такими, как компоненты ввода, компоненты рендеринга, компоненты, излучающие пулю, и так далее. В настоящее время GameComponents ссылаются на объект, который им владеет, и может его модифицировать, но сам GameObject имеет список компонентов, и им все равно, что компоненты до тех пор, пока они могут быть обновлены при обновлении объекта.
Иногда компонент имеет некоторую информацию, которую должен знать GameObject. Например, для обнаружения столкновений GameObject регистрируется с подсистемой обнаружения столкновения, которая должна быть уведомлена, когда она сталкивается с другим объектом. Подсистеме обнаружения столкновения должно знать ограничивающий объект объект. Я хранил x и y в объекте напрямую (потому что он используется несколькими компонентами), но ширина и высота известны только компоненту рендеринга, который содержит растровое изображение объекта. Я хотел бы иметь метод getBoundingBox или getWidth в GameObject, который получает эту информацию. Или вообще, я хочу отправить некоторую информацию от компонента к объекту. Однако в моем текущем проекте GameObject не знает, какие конкретные компоненты он имеет в списке.
Я могу придумать несколько способов решения этой проблемы:
-
Вместо того, чтобы иметь полностью общий список компонентов, я могу позволить GameObject иметь определенное поле для некоторых важных компонентов. Например, он может иметь переменную-член, называемую renderComponent; всякий раз, когда мне нужно получить ширину объекта, я просто использую
renderingComponent.getWidth()
. Это решение по-прежнему позволяет использовать общий список компонентов, но он относится к некоторым из них по-разному, и я боюсь, что в конечном итоге у меня будет несколько исключительных полей, так как нужно будет запросить дополнительные компоненты. Некоторые объекты даже не имеют компонентов рендеринга. -
Имейте необходимую информацию в качестве элементов GameObject, но разрешите компонентам обновлять ее. Таким образом, объект имеет ширину и высоту, которые по умолчанию равны 0 или -1, но компонент рендеринга может установить их в правильные значения в своем цикле обновления. Это похоже на хак, и я могу в конечном итоге подталкивать многие вещи к классу GameObject для удобства, даже если не все объекты нуждаются в них.
-
У компонентов есть интерфейс, который указывает, на какую информацию они могут быть запрошены. Например, компонент рендеринга реализует интерфейс HasSize, который включает такие методы, как getWidth и getHeight. Когда GameObject нуждается в ширине, он перебирает свои компоненты, проверяя, реализуют ли они интерфейс HasSize (используя ключевое слово
instanceof
в Java илиis
в С#). Это похоже на более общее решение, одним из недостатков является то, что поиск компонента может занять некоторое время (но тогда большинство объектов имеют только 3 или 4 компонента).
Этот вопрос касается не конкретной проблемы. Он часто появляется в моем дизайне, и мне было интересно, как наилучшим образом справиться с этим. Производительность несколько важна, так как это игра, но количество компонентов на объект обычно невелико (максимум 8).
Краткая версия
В системе на основе компонентов для игры, какой лучший способ передать информацию от компонентов объекту, сохраняя общий дизайн?