Войти
ПрограммированиеФорумГрафика

ECS во все поля (4 стр)

Страницы: 1 2 3 4 5 6 Следующая »
#45
8:06, 12 апр. 2020

/A\
> это было 4 мес назад, уже не помню, но исходники ковырял
ты точно перепутал и EnTT точно не использует (и никогда не использовал) mega-array, так как иначе он не смог бы реализовать perfect SoA. он использует отдельный sparse set на каждый компонент и выстраивает элементы в этом сете согласно группам, чтобы энтити, которые обладают всеми компонентами группы, были в начале массива и обладали одинаковыми индексами.

#46
9:10, 12 апр. 2020

Suslik
> ты точно перепутал и EnTT точно не использует (и никогда не использовал) mega-array
Ну ок, может это было в EntityX

#47
20:16, 15 апр. 2020

Пора поделиться болью при использовании ECS ))

Сортировка рендер компонентов. ECS под это не рассчитан, в лучшем случае можно отсортировать их в пределах одного архетипа, но это частный случай. Я остановился на варианте сделать компонент с порядковым номером, этот номер передается в рендер, а там уже расставляется все в нужном порядке.

UI на ECS. В инете можно найти доклад про оптимизацию UI на ECS, но я его так и не понял( В общем проблема тут в том, что компоненты юи должны обходиться в определенном порядке. От корня вверх при обновлении лейаутов и рисовании, и сверху вниз при обработке инпута. У меня получился почти ООП подход, добавил компонент с указателем на функцию обновления лейаута.

Допустим у нас есть несколько камер, например главная, тени, отражения, превью какое-нибудь и тд. Для каждой камеры получается свой набор видимых рендер компонентов со своими лодами. Хранить столько рендер компонентов в одном энтити совсем неудобно, в том числе из-за частых смен архетипов. Решил вынести визибилити и рендер компоненты в отдельные энтити. Примерно как в Destiny, то есть игровой объект ссылается на визибилити, там выбирается лод которые ссылается на рендер компоненты, сами рендер компоненты хранят ссылки, а сами меши, текстуры и тд хранятся в рендер кэше.

#48
(Правка: 21:31) 21:19, 15 апр. 2020

/A\
> Сортировка рендер компонентов. ECS под это не рассчитан, в лучшем случае можно
> отсортировать их в пределах одного архетипа, но это частный случай. Я
> остановился на варианте сделать компонент с порядковым номером, этот номер
> передается в рендер, а там уже расставляется все в нужном порядке.
я тож сделал именно так, только для физики. движок один раз проходится по всем энтитям через SoA массив и компоненту, который хранит индекс, назначает свой временный индекс, который валиден только для текущего кадра. с этого момента физ.движок забывает вообще про энтити и работает напрямую с массивами компонентов и этим массивом индексов. на самом деле это вышло даже лучше, чем, например, внутри солвера каждый раз по указетелю обращаться, потому что солвер использует только тот компонент, который ему нужен, а не всю энтити.

> UI на ECS. В инете можно найти доклад про оптимизацию UI на ECS, но я его так и не понял( В общем проблема тут в том, что компоненты юи должны обходиться в определенном порядке. От корня вверх при обновлении лейаутов и рисовании, и сверху вниз при обработке инпута. У меня получился почти ООП подход, добавил компонент с указателем на функцию обновления лейаута.
в чём профит ECS для гуи? каждый UI-элемент ведь может быть только одним типом компонента. он не может быть одновременно чем-то и чем-то.

/A\
> Допустим у нас есть несколько камер, например главная, тени, отражения, превью какое-нибудь и тд.
я бы сделал так (теоретизирую, у меня culling'а нет, лол): у обычных игровых объектов есть компонент AABB. есть синглтон AABBTree, который хранит в дереве хендлы на энтити. система, которая отвечает за движение объектов, также уведомляет AABBTree о том, какие энтити обновились и какой у них новый AABB. далее камера — обычное энтити, у которого есть компонент "frustum". далее CullingSystem пробегается по всем компонентам, у которых есть компонент frustum и осуществляет culling, используя синглтон с деревом и записывает в компонент RenderListComponent (для каждой камеры), какие объекты в него попали.

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

так и решил сделать и не выпендриваться: физ.движок отдельно, ECS отдельно. но в самом конце, уже когда всё реализовал, психанул и решил переписать в качестве эксперимента, чтобы физ.движок работал напрямую с энтитями. и это, блин, вышло просто офигенно. мне очень нравится, что данные не надо дублировать, не надо поддерживать два параллельных массива (массив rigid body внутри движка и массив PhysicsComponent'ов), не надо париться и отдельно обрабатывать тела, у которых есть масса, но нет геометрии. не надо париться, как менеджить память при удалении объектов: entt всё сам при этом разруливает предельно логично и предсказуемо. не надо самому поддерживать perfect SoA лейаут, так как это делает entt, предельно прозрачным образом. короче, мне пока очень понравилось такое решение. хотя для продакшена оно, конечно едва ли потянет, ибо этот подход подходит только для велосипедной физики.

#49
21:36, 15 апр. 2020

Suslik
> в чём профит ECS для гуи?
Разве что в том, что UI тоже на ECS, а не где-то в стороне.

> я бы сделал так
А как быть когда у одного игрового объекта нужно хранить разные лоды для разных камер? А у этих лодов еще списки рендер компонентов.

#50
23:42, 15 апр. 2020

/A\
> А как быть когда у одного игрового объекта нужно хранить разные лоды для разных
> камер? А у этих лодов еще списки рендер компонентов.
Лод должен быть частью рендер компонента. Можно назвать это "свойством" компонента.

#51
(Правка: 3:10) 3:04, 16 апр. 2020

Хорошая тема.
Я в своей велосипедной ECS сперва думал делать компоненты POD типами, но потом решил в архетипе хранить ссылку на деструктор / move конструктор для каждого типа компонента. Все так делают?
За презентации спасибо, посмотрю.

Suslik
> энтити — это интовый id + версия
норм идея

#52
6:17, 16 апр. 2020

/A\
> А как быть когда у одного игрового объекта нужно хранить разные лоды для разных камер? А у этих лодов еще списки рендер компонентов.
я бы хранил не по объекту на лод, а по несколько лодов на объект. как мипмапы. одна текстура — это массив мипов, а не каждый мип отдельной текстурой. но это я с дивана, лоды никогда не реализовывал.

Division
> Я в своей велосипедной ECS сперва думал делать компоненты POD типами, но потом
> решил в архетипе хранить ссылку на деструктор / move конструктор для каждого
> типа компонента. Все так делают?
я храню не ссылку, а просто использую автоматический деструктор для компонентов. хранить в явном виде ссылку на деструктор — не уверен, что хорошая идея, потому что вдруг её кто-то забудет установить? или как оно должно работать по-твоему?

#53
(Правка: 6:38) 6:32, 16 апр. 2020

Suslik
> использую автоматический деструктор для компонентов
Подробней, не понял

> или как оно должно работать по-твоему?
У меня компоненты энтитей для каждого архетипа хранятся в линкед листе чанков. Архетип это уникальный набор компонентов.
Чанк это просто память, в которой последовательно хранятся компоненты одного типа, потом другого типа итд.
Чтобы понимать, какие офсеты у каждого типа компонентов внутри чанка и какой размер каждого компонента, есть класс ComponentLayout, в котором лежит массив ComponentData:

  struct ComponentData
  {
    ComponentHash hash;
    uint32_t offset;
    uint32_t size;
    void(*destructor)(const void*);
    void(*move_constructor)(void* x, void* other);
  };

И тут же находится деструктор/мув конструктор каждого компонента.
Забыть зарегистрировать деструктор/конструктор невозможно, тк ecs делает это автоматически при добавлении компонента в ComponentLayout (это мой аналог архетипа)

+ Показать

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

#54
(Правка: 6:43) 6:42, 16 апр. 2020

Division
> У меня компоненты энтитей для каждого архетипа хранятся в линкед листе чанков.
> Архетип это уникальный набор компонентов.
если тебе интересна реализация самой ECS, можешь пообсуждать с /A\. я почитал исходники entt и пришёл к выводу, что я бы сам сделал именно так (они не используют архетипы, вместо этого используются группы, которые по сути очень близки, но с акцентом на производительности, а не на гибкости использования). поэтому я обошёл весь головняк с нопесанием своей ecs и перешёл сразу к головняку с её использованием, лол.

> component_count += 1;
правильно писать так, лол:
component_count = 1 + component_count;

#55
7:23, 16 апр. 2020

Suslik
> перешёл сразу к головняку с её использованием, лол.
А что ты пишешь?

#56
7:48, 16 апр. 2020

Division
да с algebraic multigrid solver'ами балуюсь и решил для этого дела новый тестбед быстренько накатать.

#57
(Правка: 7:50) 7:48, 16 апр. 2020

Division
> Все так делают?
У меня все компоненты POD типы, но для них вызывается конструктор. Копирование сделано через memcpy, а на удаление можно подписаться чтоб очистить связанные с ним данные.

И у меня на все изменения компонентов создаются сообщения, иногда автоматически иногда вручную.

#58
7:50, 16 апр. 2020

/A\
> У меня все компоненты POD типы, но для них вызывается конструктор.
у меня в компонентах широко применяются и std::unique_ptr, и std::vector. зачем от них отказываться?

#59
(Правка: 7:51) 7:50, 16 апр. 2020

Suslik
> у меня в компонентах широко применяются и std::unique_ptr, и std::vector. зачем от них отказываться?
Потому что все говорят, что тру екс - на POD типах)
А еще есть сообщения которые хранят копию компонента.

Страницы: 1 2 3 4 5 6 Следующая »
ПрограммированиеФорумГрафика