Как обрабатывать динамические иерархические объекты в ECS

Вот аналогия: у меня есть организм, состоящий из клеток, которые могут быть далее составлены из смеси привязанностей.

В настоящее время у меня есть своего рода цепочка событий между дочерними/родительскими элементами для обработки присоединения и отсоединения компонентов (что может повлиять на что-либо в цепочке), которая вообще не включает ecs, они являются функциями в сущностях.

Теперь я уже использовал компоненты событий (для событий мыши на объектах). Если бы я хотел, чтобы система была чистой, должен ли я создавать компонент присоединения, когда я прикрепляю компоненты и т. д.? Даже тогда, как я могу получить всех необходимых получателей для системы, которая потребляет компонент? Стоит ли вообще обрабатывать его таким образом вместо цепочки функций? Есть ли способ лучше?

Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
3
0
1 750
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Отказ от ответственности: я не уверен, что правильно понял ваш вопрос. Если это не так, прошу прощения за слухи.


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

struct relationship {
    entity_type first{entity_null};
    entity_type prev{entity_null};
    entity_type next{entity_null};
    entity_type parent{entity_null};
    // ... other data members ...
};

Где entity_type — это тип, который вы используете для идентификаторов своих объектов, а entity_null — это ваш способ сказать — это еще не установлено. Эти две вещи в основном зависят от фактической реализации. Например, в моем собственном (EnTT) существует entt::null, который является своего рода нулевая сущность для использования в таких случаях, как этот.

Давайте теперь рассмотрим общий узел в вашей иерархии: * parent — это идентификатор объекта родительского узла, так что вы можете легко пройти по дереву (иерархии) от листа к корню. * first — идентификатор сущности первых дочерних элементов, то есть список листьев или внутренних узлов поддерева, корневым узлом которого является текущий идентификатор. * prev и next — идентификаторы сущностей братьев и сестер для текущего узла.

Когда вы хотите посещать всех дочерних элементов узла, вы начинаете с объекта first (его первого дочернего элемента) и повторяете их по одному, посещая next, пока он не станет нулевым. Если вы хотите вернуться от узла к его родителю, вы можете просто использовать parent.

плюс этого решения заключается в том, что списки дочерних элементов неявно определяются с точки зрения компонентов, и вам не нужно использовать для них std::vector или подобное. Следовательно, у вас нет динамически выделяемой памяти в ваших компонентах для создания иерархии.

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

Другие вопросы по теме