GLoom
> Про сервис для покупки дешёвых авиабилетов?
>
Дискорд разве сервис для покупки авиабилетов? )
> Про сервис для покупки дешёвых авиабилетов?
А не догнал шутку сразу)
1vanK
> То есть надо еще соображать, какой компонент первым ставить? Там еще с группами какая-то замута, не разбирался пока.
Тоже не разбирался, но view довольно прямолинейно работает. Итерируешься по первому, бонсуная фильтрация по остальным. Чем сильнее фильтр, тем быстрее — поэтому самый редкий идет самым первым.
> Ну я так и без entt делал (чистил списки от уничтоженных объектов в конце апдейта):
У этого кода сложность линейная от суммарного количества объектов, а у меня — линейная от количества уничтоженных объектов. Когда событий на много порядков меньше, чем объектов, разница может быть заметной.
> Лага в кадр при этом нет в принципе, просто в каждой функции работающей в с объектом проверяешь, что он не мертв.
Да, но тут уже баланс между двумя бесячими вещами. Либо мне на каждый чих и пук проверять, что не уничтожено, либо терпеть задержку в кадр.
А если уничтожение объекта приводит к другой игровой логике, которая в свою очередь приводит к другим уничтожениям — тут лаг в кадр неизбежен, если не рефакторить и не усложнять всю систему.
Eugene
> Либо мне на каждый чих и пук проверять, что не уничтожено, либо терпеть задержку в кадр.
TBH во всех движках которые я для себя писал у меня было такое удаление - накапливание удалённых тем или иным образом и массовая чистка в конце кадров. Никогда это не мешало вроде бы.
Довольно сложно через пошаговый отладчик понять, как entt итерирует по сущностям. Такие адовые конструкции из шаблонов с кучей уровней вложенностей. Но эксперименты показали, что либа позволяет во вложенном цикле пометить сущности как удалённые и дальше они будут пропускаться. И новые добавленные тоже будут пропускаться. Итерирует к тому же в обратном порядке от добавления.
inline void test_ecs() { cout << "TEST ECS\n"; struct DelMarker {}; struct Obj { int index = 0; }; registry& reg = *GLOBAL->reg(); // Создаём сущности { entity ent = reg.create(); reg.emplace<Obj>(ent, 1); } { entity ent = reg.create(); reg.emplace<Obj>(ent, 2); } { entity ent = reg.create(); reg.emplace<Obj>(ent, 3); } { entity ent = reg.create(); reg.emplace<Obj>(ent, 4); } { entity ent = reg.create(); reg.emplace<Obj>(ent, 5); } // Цикл по неудалённым сущностям auto view1 = reg.view<Obj>(exclude<DelMarker>); cout << "FIRST LOOP\n"; for (entity ent : view1) { int ent_index = view1.get<Obj>(ent).index; cout << "STEP: ent index = " << view1.get<Obj>(ent).index << endl; if (ent_index == 3) { // Все сущности помечаем как удалённые auto view2 = reg.view<Obj>(); for (entity ent2 : view2) reg.emplace<DelMarker>(ent2); // Добавляем две новые сущности entity new_ent_1 = reg.create(); reg.emplace<Obj>(new_ent_1, 6); entity new_ent_2 = reg.create(); reg.emplace<Obj>(new_ent_2, 7); } } cout << "SECOND LOOP\n"; for (entity ent : view1) { int ent_index = view1.get<Obj>(ent).index; cout << "STEP: ent index = " << view1.get<Obj>(ent).index << endl; } cout << "END TEST ECS"; }
Результат:
TEST ECS FIRST LOOP STEP: ent index = 5 STEP: ent index = 4 STEP: ent index = 3 SECOND LOOP STEP: ent index = 7 STEP: ent index = 6 END TEST ECS
Вот допустим распиаренная ecs-концепция. Ты описал компонент - лазерная пушка. Пушку можно повесить на танк, можно на здание, танк могут подбить и гусеницы перестанут ездить, но пушка продолжит стрелять или башню с пушкой оторвет и пушка аналогично может продолжить стрелять.
Но в entt просто нельзя добавить несколько компонентов одного типа к одной сущности.
Что делать, когда у тебя самолет и на нем несколько лазерных пушек? Т.е. нельзя таким-же простым способом сделать так, чтобы одну пушку оторвало, она упала на землю, а остальные лазерные пушки продолжили стрелять.
Ну окей я создаю компонент weapons, в котором хранится массив entity, каждый из которых - лазерная пушка. Но мне же надо пушки не отдельно двигать, а вместе с самолетом. И мне уже в каждой пушке надо хранить entity родительского объекта самолёта. Короче начинается ад.
1vanK
Что мешает сделать пушки отдельными Entity? Почему они должны быть именно компонентами?
> Что мешает сделать пушки отдельными Entity? Почему они должны быть именно компонентами?
Чтобы двигать вместе с самолетом
1vanK
> Чтобы двигать вместе с самолетом
ECS не отвечает за движение)
tl;dr твоей претензии: "одномерный массив структурок не дает мне иерархию".
Ну типа да, он и не должен? Иерархию ты делаешь сам поверх него, так как тебе удобно/нужно.
Eugene
> ECS не отвечает за движение)
Я этого и не имел в виду. У самолета есть координаты, я их меняю, если пушка - отдельная сущность, а не компонент, то мне заодно надо менять координаты и всех дочерних сущностей.
Eugene
> tl;dr твоей претензии: "одномерный массив структурок не дает мне иерархию"
Нет, претензия у меня другая: почему я к сущности не могу компоненты одного типа добавить
1vanK
> Нет, претензия у меня другая: почему я к сущности не могу компоненты одного типа добавить
Почему в массив объектов можно положить только один объект по заданному индексу?
Это кстати 100% серьезный ответ на твой вопрос. Так работают массивы, by design, и EnTT работает на массивах.
Ну раз это фундаментальное ограничение ecs (которое я не понимаю, так как в том же урхо я могу несколько компонентов одного типа на ноду повесить), это ломает всю концепцию ecs на корню.
Пушка уже не может быть просто пушкой, мне надо знать уже информацию об ее родителе, появляется иерархия по которой мне надо бегать и собственно возврат к обычным методам организации структуры проекта.
А учитывая что ECS задумывался как плоская хрень, то использование в ней иерархии просто заваливание инвалида костылями
1vanK
> Ну раз это фундаментальное ограничение ecs (которое я не понимаю, так как в том же урхо я могу несколько компонентов одного типа на ноду повесить), это ломает всю концепцию ecs на корню.
Потому что урха не использует глобальный массив компонентов, и ты не можешь за О(1) полчить компонент из ноды по типу, и ты не знаешь, есть ли у тебя вообще компоненты, пока не посмотришь в каждую ноду. Платишь одной фичей за другую, все предельно честно.
Если тебе надо вектор объектов прикрепить к ноде/сущности, так прикрепи вектор.
Eugene
> Если тебе надо вектор объектов прикрепить к ноде/сущности, так прикрепи вектор.
Я же писал об этом, это приводит к иерархии, которую я хочу избежать и для которой ECS не очень приспособлен.