До сих пор системы компонентов сущностей, которые я использовал, работали в основном как artemis Java:
- Все данные в компонентах
- Независимые системы без состояний (по крайней мере, в той степени, в которой они не требуют ввода при инициализации), итерирующие по каждой сущности, которая содержит только компоненты, в которых заинтересована конкретная система
- Все системы обрабатывают свои объекты одним кликом, а затем все начинается заново.
Теперь я пытаюсь применить это к пошаговой игре впервые, с множеством событий и ответов, которые должны произойти в установленном порядке относительно друг друга, прежде чем игра сможет двигаться дальше. Пример:
Игрок А получает урон от меча. В ответ на это броня А срабатывает и снижает получаемый урон. Скорость движения А также уменьшается в результате ослабления.
- Полученный урон - это то, что вызывает все взаимодействие
- Броня должна быть вычислена и применена к входящему урону до того, как урон нанесен игроку
- Снижение скорости передвижения не может быть применено к юниту до тех пор, пока фактически не будет нанесен урон, так как он зависит от окончательного количества урона.
События также могут запускать другие события. Уменьшение урона от меча с помощью доспехов может привести к разрушению меча (это должно произойти до завершения уменьшения урона), что, в свою очередь, может вызвать дополнительные события в ответ на него, по существу, рекурсивную оценку событий.
В целом, это, кажется, приводит к нескольким проблемам:
- Множество потраченных впустую циклов обработки: большинство систем (за исключением тех вещей, которые всегда работают, например, рендеринга) просто не имеют ничего стоящего, если не «их очередь» работать, и проводят большую часть времени в ожидании входа в игру. действительное рабочее состояние. Это засоряет каждую такую систему чеками, размер которых увеличивается по мере добавления новых состояний в игру.
- Чтобы выяснить, может ли система обрабатывать сущности, присутствующие в игре, им необходимо каким-то образом отслеживать другие несвязанные состояния сущности / системы (система, ответственная за нанесение урона, должна знать, была ли применена броня). Это либо запутывает системы с множеством обязанностей, либо создает необходимость в дополнительных системах без какой-либо иной цели, кроме сканирования коллекции объектов после каждого цикла обработки и связи с группой слушателей, сообщая им, когда можно что-то делать.
Вышеупомянутые два пункта предполагают, что системы работают с одним и тем же набором объектов, которые в конечном итоге изменяют состояние, используя флаги в своих компонентах.
Другим способом решения этой проблемы является добавление / удаление компонентов (или создание совершенно новых объектов) в результате единой системной работы по улучшению состояния игр. Это означает, что всякий раз, когда система действительно имеет соответствующий объект, она знает, что ей разрешено ее обрабатывать.
Это, однако, делает системы ответственными за запуск последующих систем, затрудняя рассуждение о поведении программ, так как ошибки не будут отображаться в результате взаимодействия одной системы. Добавление новых систем также становится сложнее, поскольку их невозможно реализовать, не зная точно, как они влияют на другие системы (и, возможно, придется модифицировать предыдущие системы, чтобы вызывать состояния, в которых интересует новая система), что несколько противоречит цели иметь отдельные системы. с одной задачей.
Это то, с чем мне придется жить? Каждый пример ECS, который я видел, был в реальном времени, и действительно легко увидеть, как в таких случаях работает цикл «одна итерация на игру». И я все еще нуждаюсь в этом для рендеринга, он просто кажется неподходящим для систем, которые останавливают большинство аспектов себя каждый раз, когда что-то происходит
Есть ли какой-то шаблон проектирования для продвижения состояния игры вперед, который подходит для этого, или я должен просто вывести всю логику из цикла и вместо этого запускать ее только при необходимости?