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

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

Страницы: 1 2 3 4 5 6 Следующая »
#60
(Правка: 8:39) 8:17, 16 апр. 2020

Suslik
> зачем от них отказываться?
Ага, я не смог.
Где-то рядом была тема про удаление объекта из разных списков - такой ещё юз кейс: компонент Renderer имеет проперти DrawCallHandle. При удалении Renderer (или всей entity) вызовется деструктор DrawCallHandle, который автоматически удалит дроу кол из списка (или пометит на удаление, чтоб удалить когда надо, не суть).

/A\
> У меня все компоненты POD типы, но для них вызывается конструктор
А если всунуть в компонент какой-то не POD тип и у него в конструкторе аллокация, то это утечка? Или какой-то статик ассерт хендлит?

/A\
на удаление можно подписаться чтоб очистить связанные с ним данные.
Как выглядит подписка? Каждая entity должна подписываться или просто регистрируешь функцию очистки для нужного типа компонента?

#61
(Правка: 8:35) 8:30, 16 апр. 2020

Мне немого не по себе такое спрашивать, но кто-то, при удалении компонента, ставит на его место последний в списке, чтоб остальные не сдвигать? :) Или может у кого-то freelist компонентов, а список включает неактивные?

#62
8:53, 16 апр. 2020

Division
> Как выглядит подписка?
https://github.com/azhirnov/AE/blob/master/engine/ecs-st/Hierarch… Graph.cpp#L68

reg.AddMessageListener< Components::GlobalTransformation, MsgTag_AddedComponent >([this] (ArrayView<EntityID> entities) {....}

> А если всунуть в компонент какой-то не POD тип
Не надо так делать, там вообще был статик ассерт на is_trivial_destructible, но он не всегда корректно срабатывает, поэтому отключил его.

> но кто-то, при удалении компонента, ставит на его место последний в списке,
> чтоб остальные не сдвигать?
Многие так делают, и я тоже)

#63
8:59, 16 апр. 2020

Suslik
> я бы хранил не по объекту на лод, а по несколько лодов на объект. как мипмапы
Это не очень хорошо для многопоточки, тогда при обновлении одного лода придется лочить все рендер компоненты.
А если разделять их по камерам, то лочится только одна камера.

#64
(Правка: 9:21) 9:14, 16 апр. 2020

Division
> Мне немого не по себе такое спрашивать, но кто-то, при удалении компонента,
> ставит на его место последний в списке, чтоб остальные не сдвигать? :) Или
> может у кого-то freelist компонентов, а список включает неактивные?
общих подходов существует, как ты заметил, два. в случае с перезаписыванием последнего, все указатели потенциально становятся невалидны, но объекты остаются последовательны в памяти. в случае с free list'ом, объекты остаются на тех же местах в памяти, но доступ перестаёт быть последовательным. первый способ используется почти всегда, когда важно выжать максимум производительности при последовательной обработке объектов. второй способ используется, если хочется сохранять raw указатели после удаления одиночных объектов и/или если нужен быстрый доступ к компонтам у отдельных объектов (так как нет лишнего разыменования из sparse set в dense set). для идентификации объектов по ID'шникам в первом способе типично используется sparse set (гугли, если ещё не), во втором способе id'шники объектов всегда указывают на их место в массиве даже после удаления соседей, поэтому обращаться по id эффективнее, чем в первом. но не так эффективно итерироваться.

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

#65
13:52, 16 апр. 2020

Интересная тема. Моя реализация ecs после каждой итерации допиливания/переделывания становилась всё проще и проще. В итоге сейчас это просто набор sparse set'ов для каждого отдельного компонента и entity ref (пара id + generation). Никаких жёстких требований к компонентам нет, никаких наследований от базового класса, всё предельно минималистично. Компоненты хранятся в стандартном векторе, как и индексы sparse set, никакой ручной работы с памятью. Я также пришёл к выводу, что мне не нужен отдельный механизм сообщений, для этого отлично подходят сами компоненты. Забавно, что я сам пришёл к идеям sparse set и entity reference, также думал сделать оптимизацию на основе известных комбинаций компонентов (archetypes?), но пока не занимался этим, поскольку производительностью и так более чем доволен.

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

Пример: есть персонаж с координатами, графикой, действиями, инвентарём, etc. всё в одном компоненте.
Добавляем сущность деревцо - выделяем координаты и графику (общее) в отдельный компонент.
Добавляем ящик - выделяем инвентарь в отдельный компонент.
И так далее. Таким образом будем всегда иметь минимальный набор компонентов, описывающих все наши сущности без дублирования. Минус очевиден - процесс итеративный и потребует много переписывания. Хотя при наличии опыта и чёткого плана/списка сущностей можно попробовать спланировать разбивку заранее.

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

#66
14:07, 16 апр. 2020

Suslik
> у меня в компонентах широко применяются и std::unique_ptr, и std::vector. зачем
> от них отказываться?
Есть несколько небольших плюсов в использовании тривиальных компонентов, все из которых сводятся к тому, что с таким компонентами можно обращаться как с простыми кусками памяти:
- Контейнер компонентов (например std vector) сможет использовать оптимизации при копировании/перемещении объектов (просто копировать байты, не вызывая деструкторы/конструкторы).
- Чтобы сохранить стейт, достаточно сдампить память всех компонентов, не заморачиваясь с ручной сериализацией/десериализацией.
- Можно легко подсчитать контрольную сумму стейта, чтобы например выявлять desync в сетевой игре.
- И т.д.

#67
16:54, 16 апр. 2020

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

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


> Контейнер компонентов (например std vector) сможет использовать оптимизации при копировании/перемещении объектов (просто копировать байты, не вызывая деструкторы/конструкторы).
std::vector как раз прекрасно умеет оперировать с unique_ptr'ами и другими векторами. entt им и пользуется внутренне, поэтому поддержка всяких move-семантик и конструкторов получается автоматически.

> - Чтобы сохранить стейт, достаточно сдампить память всех компонентов, не заморачиваясь с ручной сериализацией/десериализацией.
для этого компоненты должны быть не только POD, но ещё и не содержать указателей. это ещё более сильное ограничение. кстати, entt специально поддерживает сериализацию, для этого есть вспомогательный функционал.

со всем остальным, что ты написал, я согласен. ещё раз, если не смотрел entt, посмотри. такое чувство, что ты практически то же самое переизобрёл.

#68
17:56, 16 апр. 2020

Suslik
> У меня есть опыт работы только с нашим доморощенным ECS
сколько всего систем у вас там?

#69
23:45, 16 апр. 2020

innuendo
> сколько всего систем у вас там?
Я бы сказал, что это EC, без S. Так как логика, в основном, в компонентах

#70
7:33, 17 апр. 2020

Division
> Я бы сказал, что это EC, без S. Так как логика, в основном, в компонентах
тут же речь про ECS?

#71
(Правка: 8:19) 8:18, 17 апр. 2020

Division
> Я бы сказал, что это EC, без S. Так как логика, в основном, в компонентах
ёпта не отвечай ему ничего, он щас опять превратит тему в своё медленное жевание соплей однострочными постами ни о чём.

/A\
> > у меня в компонентах широко применяются и std::unique_ptr, и std::vector.
> > зачем от них отказываться?
> Потому что все говорят, что тру екс - на POD типах)
смотри, логика рассуждений такая. в тру ECS все данные хранятся только в компонентах, так? — так. все компоненты ты хочешь, чтобы были POD, так? — так. то есть это значит, что вся программа получается в таком случае POD. включая кешы ресурсов (которые являются синглтон компонентами?). а как же RAII? я не вижу причин отказываться от RAII.

#72
8:21, 17 апр. 2020

Suslik
> пта не отвечай ему ничего, он щас опять превратит тему в своё медленное жевание
> соплей однострочными постами ни о чём.
куда мне до тебя - многострочные посты а результата ноль

#73
11:25, 17 апр. 2020

Suslik
> я не вижу причин отказываться от RAII.
Суть немного в другом. У меня есть система сообщений в ECS, изменил компонент - добавилось сообщение. Чтобы соответствовать DOD сообщения сначала накапливаются, а потом обрабатываются однотипные сообщения за один проход как обычные компоненты. Обработка сообщений это часть системы и они могут выполняться с большой задержкой, за это время компонент может еще раз измениться, поэтому в сообщении хранится копия компонента, еще и для DOD выгоднее хранить компию компонента в сообщении, и добавим еще многопоточку, тогда не нужно лочить компонент для которого было отправлено сообщение. С unique_ptr это делать сложнее, чем с POD типами.
И кстати, хранить в компоненте unique_ptr, vector и тд это уже отклонение от DOD ))

> ёпта не отвечай ему ничего, он щас опять превратит тему в своё медленное жевание соплей однострочными постами ни о чём.
вы просто не умеете его троллить))

#74
11:30, 17 апр. 2020

/A\
> И кстати, хранить в компоненте unique_ptr, vector и тд это уже отклонение от DOD ))
ну здесь всё-таки надо провести для себя линию между практической применимостью и фанатичным следованием правилам. DOD формулируется не господом богом, а людьми, и нет никакой гарантии, что их формулировка является безупречной. that being said, я понимаю твою идею и вижу в ней логику, но следовать ей не намерен, так как не считаю это достаточной причиной.

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