Entity Component System
- title
- Entity Component System
- type
- concept
- summary
- Data-oriented архитектура: сущности как ID, компоненты как данные, системы как пакетные итераторы
- tags
- architecture, game-dev, data-oriented-design
- created
- 2026-04-10
- updated
- 2026-04-10
- lang
- ru
- translation_of
- entity-component-system
- source_updated
- 2026-04-10
- translated
- 2026-09-01
- translator
- lllm/antigravity/gemini-3.7-flash-medium
Entity Component System (ECS) - паттерн data-oriented архитектуры, в котором объекты разделяются на три части: сущности (идентичность), компоненты (данные) и системы (поведение). Он заменяет иерархии классов композицией: вместо class Player extends Character extends Entity получается сущность с прикреплёнными компонентами Position, Health, Sprite и PlayerInput, а также системы, которые итерируют по конкретным комбинациям компонентов.
Три составляющие:
Сущности (Entities) - это просто идентификаторы. Сущность представляет собой uint64 или дескриптор с учётом поколений (generation-indexed handle); у неё нет собственных данных или поведения. Это метка, к которой привязываются компоненты.
Компоненты (Components) - простые структуры данных: Position{X, Y float64}, Velocity{DX, DY float64}, Health{Current, Max int}. Никаких методов, никакого наследования, никакого полиморфизма. Компоненты прикрепляются к сущностям во время выполнения и могут динамически добавляться или удаляться, меняя то, чем сущность является, без изменения её типа в системе типов языка.
Системы (Systems) - функции, которые запрашивают сущности, подходящие под фильтр компонентов, и итерируют по ним. Физическая система запрашивает все сущности одновременно с Position и Velocity, считывает скорость и обновляет позицию. Система отрисовки запрашивает все сущности с Position и Sprite и отрисовывает их. Системы ничего не знают друг о друге и не хранят ссылок на конкретные сущности - они работают со множеством сущностей, соответствующих их фильтру.
Почему это работает
Главный выигрыш заключается в расположении данных в памяти. В традиционной ООП-игре объект Player хранит все свои поля в одной аллокации в куче: позицию, скорость, здоровье, состояние ИИ, данные для отрисовки, инвентарь. Итерация по всем позициям означает переход по указателям через разнородные объекты, что крайне неэффективно для кэша процессора.
В ECS на базе архетипов (archetype-based) все сущности с одинаковым набором компонентов ("архетипом") хранятся в непрерывных массивах, по одному на каждый тип компонента. Итерация по всем компонентам Position превращается в линейный проход по плотному массиву. Для prefetcher'а кэша процессора это идеальный сценарий. Для систем, обрабатывающих тысячи сущностей за кадр (физика, коллизии, отрисовка), разница может достигать порядка.
Archetype-based против sparse-set
Две основные стратегии хранения:
Archetype-based (используется в Unity DOTS, Bevy, Ark): сущности группируются по комбинации компонентов. Добавление или удаление компонента перемещает сущность в таблицу другого архетипа. Итерация максимально эффективна для кэша; мутация компонентов (добавление/удаление) обходится дороже, так как требует перемещения между таблицами.
Sparse-set (используется в EnTT, flecs до версии v4): для каждого типа компонентов есть собственный sparse set, сопоставляющий ID сущностей с плотным хранилищем. Итерация в рамках одного компонента быстрая, но запросы по нескольким типам компонентов требуют пересечения множеств. Добавление и удаление обходятся дёшево - достаточно вставить элемент в набор или удалить из него.
Большинство современных ECS-фреймворков склоняются к archetype-based, поскольку нагрузка с преобладанием итераций (игровой цикл, такт симуляции) на практике значительно превышает операции добавления и удаления.
За пределами игр
ECS естественен для игровых движков, но паттерн применим везде, где есть большая коллекция разнородных сущностей, обрабатываемых пакетами. Симуляции (агентное моделирование, системы частиц), робототехника (потоки данных с сенсоров через конвейеры обработки) и процессы обработки данных - всё это отлично укладывается в ECS. Главный вопрос в том, какова специфика нагрузки: "итерировать по множеству сущностей, выполняя одну и ту же операцию" (здесь выигрывает ECS) или "выполнять сложные операции над отдельными объектами" (для этого вполне подходит ООП).
behavior-tree служит дополняющим паттерном: он отвечает за логику принятия решений для отдельных сущностей, тогда как ECS берёт на себя организацию данных в памяти и массовую обработку. И go-bt, и Ark - это библиотеки на Go, которые можно объединить в игре или симуляции.