Используя систему компонентов сущности, как обеспечить наличие не более одного компонента (для каждой сущности) из группы типов компонентов?

Я использую ecs в течение некоторого времени, но есть проблема, для которой я не смог найти хорошего, в основном общего решения. Существует группа типов, максимум один из которых должен быть связан с объектом. Бывший. есть некоторая логика триггера. Все триггеры (одного типа) могут быть оценены сразу в обычной параллельной итерации. Все работает нормально, но не имеет смысла иметь несколько триггеров для одного объекта. На данный момент у меня есть всевозможные системы (задачи) очистки и проверки работоспособности, которые необходимо всегда обновлять при создании нового типа триггера. (Редактировать при обновлении, я имею в виду исходный код, а не среду выполнения.) В традиционном oop это было бы тривиально: сохранить один указатель для каждой сущности на базовый тип, получить и реализовать новый риггер, и это Это. В ecs они хранятся в разных хранилищах, и у меня нет хорошего решения, чтобы обеспечить для них какое-то взаимное исключение.

Спасибо за любые предложения.


person Gzp    schedule 11.05.2019    source источник


Ответы (1)


У меня есть всевозможные системы (задачи) очистки и проверки работоспособности, которые необходимо всегда обновлять при создании нового типа триггера.

...

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

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

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

Эта TriggerSanityCheckSystem будет запускаться перед любой другой системой триггеров, чтобы гарантировать требование взаимной исключительности, которое вам нужно до того, как разрешить выполнение логики компонента для триггеров.

ОБНОВИТЬ

Здесь может быть лучший подход, но я просто не уверен, подойдет ли он к вашему дизайну. В своем исходном вопросе вы упомянули следующее:

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

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

struct TriggerDelegatingComponent 
{
  BaseTrigger *delegate_;
}

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

В этом подходе вы смешиваете лучшее из обоих миров, ECS и OOP.

person Naros    schedule 11.05.2019
comment
Извините, я недостаточно конкретизировал свой вопрос. Под обновлением я имею в виду обновление исходного кода, а не среды выполнения. При создании нового типа триггера мне приходится расширять срабатывание триггеров. Также он должен заблокировать все компоненты триггера, что может быть нормально. Но увеличивающееся количество вводных данных для задачи просто неприятно. - person Gzp; 11.05.2019
comment
Технически я делаю то, что было предложено, но поскольку системы в моей реализации чистые и могут не иметь состояния, уведомление выполняется компонентом тега. Но основной алгоритм / идея такая же, как вы описали. - person Gzp; 11.05.2019
comment
@Gzp См. Мое обновление моего ответа, я думаю, что это может быть более применимо здесь после некоторых размышлений по проблеме. - person Naros; 15.05.2019
comment
Вы имеете в виду хранить всю логику (несколько компонентов) для одного объекта и иметь контроллер, который делегирует фактическую логику текущему, игнорируя другие? Это может работать, но имеет некоторый риск в отношении управления памятью. Я должен заставить этот контроллер никогда не указывать на выпущенную логику. - person Gzp; 16.05.2019
comment
Другая версия вышесказанного: контроллер имеет одно перечисление, указывающее на текущую логику. При одновременном обновлении всех компонентов перечисление можно использовать в качестве фильтра для пропуска неактивной логики. - person Gzp; 16.05.2019
comment
Более того, при обновлении могут быть освобождены неиспользуемые компоненты логики (для меня это похоже на план). Спасибо за идею контроллера. Воздействие для создания нового триггера: создать новую композицию, создать новое перечисление. Никаких изменений в существующем коде. - person Gzp; 16.05.2019