- PVSM.RU - https://www.pvsm.ru -
Сколько уже было мануалов "Как сделать игру на Unity за 3 часа", "Делаем Counter-Strike за вечер" и т.п.? Низкий порог входа — это, несомненно, главный плюс и минус Unity. Действительно, можно накидать “ассетов”, дописать несколько простых “скриптов”, обмотать синей изолентой и это даже будет как-то работать. Но когда проект обрастает игровыми механиками, сложной логикой поведения, то проблемы при подобном подходе нарастают как снежный ком. Для внедрения новых механик требуется переписывание кода во многих местах, постоянная проверка и переделывание префабов из-за побившихся ссылок на компоненты логики, не говоря уже об оптимизации и тестировании всего этого. Разумеется, архитектуру можно продумать изначально, но на практике это всегда недостижимая цель — дизайн-документ довольно часто меняется, какие-то части выкидываются, добавляются абсолютно новые и никак не связанные со старой логикой поведения. Компоненты в Unity — это шаг в правильном направлении в виде декомпозиции кода на изолированные блоки, но особенности реализации не позволяют достичь необходимой гибкости, а самое главное, производительности. Разработчики придумывают свои фреймворки и велосипеды, но чаще всего останавливаются на ECS (Entity Component System). ECS – одно из решений, продолжающее идею компонентной модели Unity, но придающее ей ещё больше гибкости и сильно упрощающее рефакторинг и дальнейшее расширение приложения новым функционалом без кардинальных изменений в текущем коде.
ECS — это шаблон проектирования "Сущность Компонент Система" (Entity Component System, не путать с Elastic Cloud Storage :). Если совсем по-простому, то есть “Сущности” (Entity) — объекты-контейнеры, не обладающие свойствами, но выступающие хранилищами для “Компонентов”. “Компоненты” — это блоки данных, определяющие всевозможные свойства любых игровых объектов или событий. Все эти данные, сгруппированные в контейнеры, обрабатываются логикой, существующей исключительно в виде “Систем” — “чистых” классов с определенными методами для выполнения. Данный паттерн является независимым от какого-либо “движка” и может быть реализован множеством способов. Все “сущности”, “системы” и “компоненты” должны где-то храниться и каким-то образом инициализироваться — все это является особенностями реализации каждого ECS решения для конкретного “движка”.
Постойте, скажете вы, но ведь в Unity всё так и есть! Действительно, в Unity “Сущность” — это GameObject, а “Компонент” и “Система” — это наследники MonoBehaviour. Но в этом и заключается основное различие между компонентной системой Unity и ECS — логика в ECS обязательно должна быть отделена от данных. Это позволяет очень гибко менять логику (даже удалять / добавлять её), не ломая данные. Другой бонус — данные обрабатываются “потоком” в каждой системе и независимо от реализации в “движке”, в случае с MonoBehaviour происходит довольно много взаимодействия с “Native”-частью, что съедает часть производительности. Об особенностях внутреннего устройства вызова методов у наследников MonoBehaviour можно почитать в официальном блоге Unity: 10000 вызовов Update() [1]
Задача от дизайнера: “надо сделать перемещение игрока и загрузку следующего уровня, когда он доходит то точки Х”.
Разбиваем задачу на несколько подзадач, по одной на “систему”:
Определяем компоненты:
И вот как это всё примерно работает:
Выглядит как чрезмерное усложнение кода по сравнению с одним “MonoBehaviour” классом в десяток строк, но изначально:
Исходя из примера выше, можно вывести основные особенности ECS по отношению к компонентной модели Unity.
Плюсы
Минусы
Для многих, кто долго работал с Unity и ни разу не использовал ECS, поначалу будет сложно привыкнуть к такому подходу. Но вскоре, начинаешь “думать” компонентами / системами и всё собирается быстрее и легче, чем при сильно связанных компонентах на базе “MonoBehaviour”.
Сейчас даже сами разработчики Unity поняли, что пора что-то менять в их компонентной системе, чтобы повысить производительность приложений. Где-то год назад было анонсировано, что ведётся разработка собственной ECS и C# Job system. И вот, в 2018.1 версии, мы уже можем примерно представить, что же это будет в будущем, пусть даже и в Preview статусе [2].
Со штатной Unity ECS – пока ничего не понятно. Разработчики нигде не пишут, что она подходит только для ограниченного спектра задач, но когда возникают вопросы в результате переписывания с других ECS-решений — отвечают в стиле “вы неправильно используете ECS”. Т.е. по сути это получается не “multipurpose”-решение, что довольно странно. Релиза не было, всё еще могут поменять несколько раз, есть проблемы с передачей ссылочных типов (например, string), поэтому я не могу порекомендовать делать что-то большое на штатной ECS в её текущем состоянии.
ECS-паттерн был придуман не вчера и на https://github.com [3] можно найти множество его реализаций, включая версии для Unity. Относительно свежие и обновляющиеся:
Я имел дело только с двумя первыми вариантами.
Entitas — самое популярное и поддерживаемое большим сообществом решение (потому что было первым). Оно достаточно быстрое, есть интеграция с Unity-редактором для визуализации ECS-объектов, присутствует кодогенерация для создания оберток с удобным api поверх пользовательских компонентов. За последний год кодогенератор отделился в независимый проект и стал платным, так что это скорее минус. Еще один достаточно весомый минус (особенно для мобильных платформ) — память выделяется под все возможные варианты компонентов на каждой сущности, что не очень хорошо. Но в целом, он хорош, отлично документирован и готов к использованию на реальных проектах. Размер: 0.5mb + 3mb поддержки редактора.
Примеров с использованием Entitas [8] достаточно много, но и существует / пиарится [9] проект давно. Из примеров с исходниками можно посмотреть Match 1 [10].
Общая производительность Entitas оценивается примерно так:
С LeoECS я знаком лучше, потому что делаю на нём новую игру. Оно компактное, не содержит закрытого кода в виде внешних сборок, поддерживает assembly definitions из Unity 2017, более оптимизировано по использованию памяти, практически нулевой GC (только на первичном наборе пулов), никаких зависимостей, C# v3.5 с опциональной поддержкой inline-ов для FW4.6. Из приятных вещей: DI через разметку атрибутами, интеграция с Unity-редактором для визуализации ECS-объектов и готовая обвязка для событий uGUI. размер: 18kb + 16kb поддержки редактора.
В качестве готового примера с исходниками можно посмотреть классическую игру "Змейка" [11].
Сравнение скорости Entitas и LeoECS [12]: результаты достаточно близки с небольшим перевесом в ту и другую сторону.
Я не эксперт в данном вопросе (только недавно начал использовать Unity в связке с ECS), поэтому и решил поделиться своими наблюдениями и мыслями в первую очередь с теми, кто "собирает" игры на Unity из ассетов с кучей скриптов на каждом. Да, это работает. Сам такой был. Но если вы делаете не прототип или какую-нибудь одноразовую игру без необходимости её поддержки и дальнейшего развития, то подумайте 10 раз — вам же потом во всём этом разбираться и переделывать.
Используя ECS я даже получаю удовольствие от процесса рефакторинга :) В игру легко добавляются новые фичи, изменяются старые — и всё это без боли и конфликтов с дизайнером, решившим добавить новую зубодробительную механику или удалить старые, наигравшись с ними.
Автор: Игорь
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/279739
Ссылки в тексте:
[1] 10000 вызовов Update(): https://blogs.unity3d.com/ru/2015/12/23/1k-update-calls/
[2] пусть даже и в Preview статусе: https://forum.unity.com/forums/entity-component-system-and-c-job-system.147/
[3] https://github.com: https://github.com
[4] Entitas: https://github.com/sschmid/Entitas-CSharp
[5] LeoECS: https://github.com/Leopotam/ecs
[6] BrokenBricksECS: https://github.com/Spy-Shifty/BrokenBricksECS
[7] Svelto.ECS: https://github.com/sebas77/Svelto.ECS
[8] Примеров с использованием Entitas: https://github.com/sschmid/Entitas-CSharp/wiki/Made-With-Entitas
[9] пиарится: https://www.youtube.com/watch?v=1wvMXur19M4
[10] посмотреть Match 1: https://github.com/sschmid/Match-One
[11] посмотреть классическую игру "Змейка": https://github.com/Leopotam/ecs-snake
[12] Сравнение скорости Entitas и LeoECS: https://github.com/echeg/unityecs_speedtest
[13] Источник: https://habr.com/post/358108/?utm_source=habrahabr&utm_medium=rss&utm_campaign=358108
Нажмите здесь для печати.