Создание сущности как агрегации


10

Недавно я спросил о том, как отделить сущности от их поведения, и основной ответ, связанный с этой статьей: http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

Конечная концепция, написанная здесь, такова: ОБЪЕКТ КАК ЧИСТАЯ АГРЕГАЦИЯ.

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

Мое текущее мышление все еще включает в себя наличие конкретного класса для каждого типа сущности, который затем реализует соответствующие интерфейсы (IMoveable, ICollectable, ISpeakable и т. Д.).

Как я могу создать сущность в виде агрегации, не имея конкретного типа для этой сущности?


Если вы все еще заинтересованы, я могу выслать вам свою маленькую систему сущностей на C #. Это не удивительно , но это работает.
Коммунистическая утка

Ответы:


6

Подход «чистой агрегации», описанный Вестом в этой статье, полностью исключает объект «сущность». Есть компоненты, плавающие в памяти, но они связаны друг с другом только неявными отношениями, если вообще существуют.

Одним из способов сделать это является так называемый подвесной подход . В такой системе компоненты хранятся в системах, которые управляют ими или иным образом контролируют их (здесь я использую термин «управлять», но не следует понимать, что это означает, что я предлагаю иметь несколько классов * Manager для хранения). типы компонентов). Например, ваша физическая система может удерживать кучу вещей, представляющих каждое твердое тело в мире симуляции, и может представлять эти вещи как физические компоненты. Компоненты могут быть фактическими объектами, обрабатываемыми рассматриваемой подсистемой, или они могут быть при необходимости прокси-серверами для этих объектов.

В такой системе необязательно, чтобы класс «Entity» содержал коллекцию ссылок на составляющие его компоненты; вместо этого выдается уведомление о создании или уничтожении «объекта», и каждая подсистема, которая обрабатывает компоненты, просматривает описание созданного / уничтоженного объекта (который обычно загружается из некоторых данных) и определяет, необходим ли для него компонент.

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

Существует несколько хороших способов реализации систем объектно-ориентированных игровых объектов; это на самом деле, действительно, действительно помогает , если у вас есть четкое представление о требованиях , которые вы хотите из вашей системы - вы можете посмотреть на то , что популярные рамки как Unity сделать для примеров. Не устанавливая для себя строгих требований, вы можете столкнуться с проблемой бесконечного «проектирования» системы, даже не создавая ее, пытаясь напрасно достичь идеальной реализации. По какой-то причине я часто видел это с компонентными системами.


3

Unity делает так, что все сценарии (в вашем случае игровой код, специфичный для типа игрового объекта) происходят из базового класса MonoBehaviour, который сам по себе является производным от класса, более подходящего для вашего случая Component. Вы никогда не редактируете (и не имеете доступа к коду) класс GameObject.

Игровой объект отвечает за содержание всех этих Components. Это также якобы отвечает за вызов соответствующих функций на них (то есть Update). Unity использует отражение, чтобы определить, какие функции вызывать (смотрите раздел «Перезаписываемые функции» на этой странице ), но вы, вероятно, захотите сделать их виртуальными.

Таким образом, один из механизмов, которые вы используете в Unity, - это получение компонентов вашего текущего игрового объекта (или его дочерних элементов) по типу. Есть некоторые вспомогательные свойства, которые обертывают некоторые общие вещи. Например, если вы хотите получить доступ к Transformкомпоненту игрового объекта (для управления позицией / вращением / масштабом игрового объекта), вам, как правило, придется сделать что-то подобное this.GetComponent<Transform>().position, но они обернут это в this.transform.positionвызов помощника . Другой распространенный шаблон - доступ к Rendererкомпоненту текущего игрового объекта . Поэтому, если вы хотите что-то сделать, например, изменить материал текущего игрового объекта, из другого скрипта вы можете сделать что-то подобное this.renderer.material = someOtherMaterial, и ваш игровой объект обновится соответствующим образом.

Один из способов, которым это работает в Unity, заключается в том, что их редактор настроен так, что вы можете создавать игровые объекты на вашей сцене, у которых уже есть подключенные компоненты. В случае Unity все игровые объекты имеют Transformкомпонент, но он также может содержать встроенные типы, такие как AudioListenerили Renderer, которые делают то, что вы ожидаете. Или вы можете добавить свои собственные компоненты, которые делают то, что вы хотите, чтобы они делали. Редактор также предоставляет открытые / сериализуемые поля для ваших компонентов, поэтому вам не нужно создавать разные сценарии, если вы хотите использовать один и тот же базовый код, но изменить несколько магических чисел вокруг.

В общем, это довольно изящно, и я бы посоветовал скачать бесплатную версию Unity и поэкспериментировать с тем, как их система сценариев настроена как довольно приличное доказательство того, чего вы хотите достичь.


0

Мне нравится подход, более близкий к видению Адама из блога t-machine. Компоненты должны быть только данными, и системы выполняют всю работу с ними.

Смотрите пример реализации ES в C #: https://github.com/thelinuxlich/artemis_CSharp

И пример игры с его использованием (XNA 4): https://github.com/thelinuxlich/starwarrior_CSharp

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.