Комментарии 18
"Классическая" версия не использует спарсеты, там просто пулы с масками компонентов на энтитях и дикты в фильтрах. Советую поглядеть кишки lite-версии, там больше нет никаких масок компонентов и все на спарсетах (пулы, фильтры). Ну и да, нет больше никакой статики в ядре - плохая идея была позаимствована.
Про итерацию через лямбду - это очень медленно, она не инлайнится и в итоге колбек вызывается для каждой энтити, но думаю ты это и так знаешь.
Про сортинг энтитей "по порядку" - это тоже возможно в лайте как постпроцессинг, причем порядок можно задавать самому на основе данных с энтити.
В каждом тике система пробегалась по всем энтити и выбирала соответствующие, но производительность такого подхода оказалась, мягко говоря, неудовлетворительной.
Надо было бежать не по всем, а по самому короткому пулу из констрейнтов с чеком остальных на совместимость - это резко уменьшает количество перебираемых данных в общем случае. Такие проверки дают падение производительности на 20% примерно, но зато убирают необходимость фильтров в принципе - это дает буст на перекладывании данных по фильтрам (убирает все накладные расходы), что чаще является затыком, чем линейный процессинг.
лямбда вызывается один раз для всей коллекции фильтрованных энтити, а так да, заметил что не очень быстро =)
А, не заметил, сорян. Да, тогда нормально, но зачем лямбда, если можно через тот же итератор и foreach-loop или просто через for-loop?
в чем минус масок?
Их конечность. Изначально классика была на масках и была лимитирована 64 (1x ulong) компонентами. Потом было расширение на 128, 256, 512 (2-4-8x ulong). Но в любом случае сразу прилетел фидбек. И пришло осознание, что проверка масок много жрет - в случае 512 компонентов это 8 итераций цикла по полной маске. В итоге маски были выкинуты и вместо них стал массив интов индексов типов (пулов) компонентов, повешенных на энтити. В среднем на энтити висит 4-6 компонентов, т.е будет 4-6 итераций для проверки совместимости энтити с фильтрами, что уже выгоднее. И к тому же количество компонентов в мире не ограничено.
А что плохого в статике для получения индекса типа (EcsComponentType<T>.TypeIndex)? Есть какая-то проблема?
Есть - статика сама по себе. Если захочешь нормально крутить несколько миров параллельно в мультитреде - статику придется очень аккуратно обмазывать синхронизацией. В лайте больше нет никакой статики и контекст мира со всеми компонентными пулами может работать безопасно в своем потоке не влияя на миры, работающие параллельно в другом (полезно на сервере, например). Ну и если кому нужна статика - ее можно намазать поверх, а не пытаться жить с ней просто потому что автор вот так решил.
Прекрасная статья, а автор красавчик
Ecs-подход рассматривается с 2 сторон - как архитектурный, так и перфоманс-паттерн. Dots - это не ecs, а скорее dod, ecs там пришит сбоку. К слову, в большинстве популярных фреймов возможно использование jobs/burst, т.е тот самый dod вполне возможен и вне dots. В общем, когда берут 3dparty ecs-фрейм - пытаются как раз не в dod, а в архитектуру. Архитектурно ecs дает легкость рефакторинга, расширяемость - можно перекроить все механики достаточно быстро, что невозможно в случае классического ООП подхода (ригидность иерархии наследования и вот все это). Об этом писалось не раз, в том числе и на хабре.
среди адептов ецс есть большой холливар на тему: "что первично- удобство разработки или производительность" я отношусь к первому лагерю. но даже без нативности DOTS производительность все равно будет выше за счет локальности данных
Эти любители аббревиатур.. У нас ECS это Enterprise Container Service или Elastic Container Service и я долго пытался понять о чем идет речь в стате и где тут ентерпрайз. Хорошо что в одной из статей по ссылке получил расшифровку.
Наверное стоит в начале статьи дать вашу расшифровку, потому что даже гугл считает что ECS это что-то связанное с кубернетес/openshift
Отличная статья, спасибо автору!
Что у ECS под капотом