Примечание: я программирую это в Javascript, но в большинстве случаев это не зависит от языка.
Я думаю о преобразовании моего двигателя в ECS.
Я понял основную идею ( примечание: это неправильно, см. Мой ответ ):
Сущности - это игровые объекты.
Компоненты - это биты функций ( reactToInput()
) или состояний ( position
), которые могут быть «приклеены» к объектам.
У систем есть список объектов, которыми они управляют и которые обновляют.
Но я не совсем уверен, что я получу реализацию и некоторые детали ...
Вопрос: может ли система работать на разных типах объектов? Я обычно привожу пример класса, называемого Scene
в моем движке, и он будет служить этой цели и сейчас. Сцена - это контейнер всех объектов, которые можно рендерить, обновлять, влиять на рендеринг (источники света) и, возможно, в будущем даже 2DSoundEmitter
объекты. Он имеет высокоуровневый интерфейс, поэтому пользователю не нужно беспокоиться о типе объекта, который он использует scene.add()
, и о подобных вещах.
Я понимаю, что это Scene
может быть система. Он принимает сущности, сохраняет их, а затем может вызывать их методы обновления и, возможно, даже вносить некоторые изменения состояния. Но есть проблема: как я описал выше, Scene
можно кормить разные типы объектов! Что я должен делать, скажем, в ситуации, когда в сцене есть как визуализируемые объекты («нарисованные объекты»), так и источники света? Должен ли я сделать проверку типа объектов перед взаимодействием? Или я должен решить его на еще более низком уровне: сделать LightSource
компонент , который может быть добавлен к любому объекту, и свет будет просто лицо с LightSource
и Position
компонентами. Это приемлемо?
Кроме того, стоит ли по-прежнему использовать обычное наследование и традиционные классы? Например, я просто не могу понять, кем бы я Renderer
был! Это не система, поскольку ее единственная функция - снимать камеру и сцену, визуализировать все и применять эффекты (например, тени). Он также управляет контекстом, шириной и высотой игры, делает переводы ... Но это еще не система!
Изменить: не могли бы вы связать какие-либо ресурсы, которые вы нашли в ECS? У меня проблемы с поиском хороших.
Ответы:
Позвольте мне понять, могу ли я помочь, пытаясь понять, как разработчик веб-интерфейса или JS-разработчика. Кроме того, не заходите слишком далеко в языковой агностицизм. Многие шаблоны, установленные на других языках, заслуживают изучения, но могут быть применены в JS совсем по-другому из-за его гибкости или действительно не являются необходимыми из-за податливой природы языка. Вы можете упустить некоторые возможности, если напишите свой код, думая, что JS имеет тот же набор границ, что и более классический ООП-ориентированный язык.
Прежде всего, о факторе «не используйте ООП», помните, что объекты JavaScript похожи на playdough по сравнению с другими языками, и вам действительно нужно изо всех сил создать кошмар каскадной схемы наследования, поскольку JS не класс на основе и композитинг приходит гораздо более естественным образом. Если вы внедряете в JS какую-то глупую классную или прототипную систему ручной работы, подумайте об отказе от нее. В JS мы используем замыкания, прототипы и передаем функции, как конфеты. Это отвратительно, грязно и неправильно, но также мощно, кратко, и так нам нравится.
Подходы с тяжелым наследованием на самом деле прописаны в шаблонах проектирования как анти-шаблон, и на это есть веская причина, как если бы каждый, кто прошел класс более 15 уровней или классоподобных структур, попытался выяснить, где, черт возьми, взломанная версия метода приходил от могу вам сказать.
Я не знаю, почему так много программистов любят это делать (особенно Java-парни, пишущие JavaScript по какой-то причине), но это ужасно, неразборчиво и совершенно не поддерживается, когда используется в избытке. Наследование хорошо здесь и там, но не обязательно в JS. В языках, где это более заманчивый ярлык, он действительно должен быть зарезервирован для более абстрактных архитектурных задач, а не для более буквальных схем моделирования, таких как frankensteining реализация зомби через цепочку наследования, которая включала BunnyRabbit, потому что это работало. Это не очень хорошее повторное использование кода. Это кошмар обслуживания.
Как движок на основе JS-разработчика, основанный на сущностях / компонентах / системах, я представляю собой систему / шаблон для разделения проблем проектирования и последующей компоновки объектов для реализации на высоком уровне детализации. Другими словами, детская игра на языке, подобном JavaScript. Но позвольте мне посмотреть, правильно ли я начинаю это делать.
Сущность - конкретная вещь, которую вы разрабатываете. Мы говорим больше в направлении имен собственных (но не на самом деле, конечно). Не «сцена», а «IntroAreaLevelOne». IntroAreaLevelOne может находиться в каком-либо блоке sceneEntity, но мы концентрируемся на чем-то конкретном, что отличается от других связанных вещей. В коде сущность на самом деле является просто именем (или идентификатором), связанным с кучей вещей, которые необходимо внедрить или установить (компоненты), чтобы быть полезными.
Компоненты - типы вещей, в которых нуждается организация. Это общие существительные. Нравится WalkingAnimation. В рамках WalkingAnimation мы можем получить более конкретную информацию, например, «Shabing» (хороший выбор для зомби и растительных монстров) или «ChickenWalker» (отлично подходит для роботов с обратной связью ed-209ish). Примечание: Не уверен, как это могло бы отделить от рендеринга 3D-модели, подобной этой, так что, может быть, это дерьмовый пример, но я скорее профессионал JS, чем опытный разработчик игр. В JS я бы поместил механизм сопоставления в одну коробку с компонентами. Компоненты сами по себе, вероятно, будут лёгкими в логике и большей части дорожной карты, сообщающей вашим системам, что следует реализовывать, если системы даже необходимы (в моей попытке ECS некоторые компоненты являются просто наборами наборов свойств). Как только компонент установлен, он '
Системы - Настоящая программа мяса здесь. Системы ИИ построены и связаны, рендеринг достигнут, последовательности анимаций установлены и т. Д. Я собираюсь выделить их, оставляя в основном воображению, но в примере System.AI принимает множество свойств и выплевывает функцию, которая используется для добавления обработчиков событий к объекту, который в конечном итоге используется в реализации. Ключевым моментом в System.AI является то, что он охватывает несколько типов компонентов. Вы могли бы разобрать все вещи ИИ с одним компонентом, но сделать это - неправильно понять смысл детализации.
Помните о целях: мы хотим упростить подключение некоторого графического интерфейса для тех, кто не является дизайнером, чтобы легко настраивать различные виды контента, максимизируя и сопоставляя компоненты в рамках парадигмы, которая им понятна, и мы хотим уйти от популярные схемы произвольного кода, которые гораздо проще написать, чем модифицировать или поддерживать.
Так что в JS может быть как то так. Разработчики игр, пожалуйста, скажите мне, если я неправильно понял:
Теперь в любое время, когда вам нужен NPC, вы можете строить с
npcBuilders.<npcName>();
Графический интерфейс может подключаться к объектам npcEntities и компонентов и позволяет дизайнерам настраивать старые объекты или создавать новые, просто смешивая и сопоставляя компоненты (хотя там нет механизма для компонентов не по умолчанию, но специальные компоненты могут быть добавлены на лету в код, пока существует определенный компонент для него.
источник
Я читал об Entity Systems в статьях, которые любезно предоставили люди в комментариях, но у меня все еще были некоторые сомнения, поэтому я задал еще один вопрос .
Во-первых, мои определения были неверны. Сущности и компоненты - просто тупые держатели данных, в то время как системы предоставляют все функциональные возможности.
Я узнал достаточно, чтобы покрыть большую часть моего вопроса здесь, поэтому я отвечу на него.
Scene
Класс я говорил не должна быть система. Тем не менее, он должен быть центральным менеджером, который может хранить все объекты, облегчать сообщения и, возможно, даже управлять системами. Он также может функционировать как своего рода фабрика для сущностей, и я решил использовать его таким образом. Он может принимать любой тип объекта, но затем он должен передавать этот объект в соответствующую систему (которая по соображениям производительности не должна выполнять никаких проверок типов, если только они не являются побитовыми).Я не должен использовать ООП при реализации ES, предлагает Адам, но я не вижу причин, чтобы не иметь объектов с методами как для сущностей, так и для компонентов, а не только для глупых держателей данных.
Renderer
Может просто быть реализован в виде системы. Он будет вести списокdraw()
доступных для рисования объектов и каждые 16 мс будет вызывать метод их компонента рендеринга.источник
Введение в управление зависимостями 101.
Этот курс предполагает, что у вас есть базовые знания по внедрению зависимостей и проектированию репозитория.
Внедрение зависимостей - это просто причудливый способ для объектов общаться друг с другом (посредством сообщений / сигналов / делегатов / чего угодно) без прямой связи.
Это идет по фразе: «
new
это клей».Я буду демонстрировать это в C #.
Это базовая система ввода, перемещения и рендеринга. В
Player
этом случае класс является сущностью, а компоненты - интерфейсами.Player
Класс ничего не знает о внутреннем , как конкретнаяIRenderSystem
,IMovementSystem
илиIInputSystem
работе. Однако интерфейсы предоставляют способPlayer
отправки сигналов (например, вызов Draw в IRenderSystem), независимо от того, как достигнут конечный результат.Например, возьмите мою реализацию IMovementSystem:
MovementSystem
может иметь свои зависимости иPlayer
даже не заботиться. С помощью интерфейсов можно создать игровой автомат:И это начало прекрасной игры (которая также может быть проверена модулем).
И с несколькими дополнениями и некоторым полиморфизмом:
Теперь у нас есть примитивная система сущностей / компонентов, основанная на агрегирующих интерфейсах и свободном наследовании.
источник