Этот материал обзорный и предназначен скорее для популяризации ECS, чем для решения конкретных проблем. Конечно люди удаляют данные и, если того требует задача, заботятся о сиротах и висячих ссылках, но какого-то автоматизированного или единственно правильного решения задач подобного рода нету, ибо каждая задача требует своего решения исходя из своей специфики и особенностей используемого подхода.
Если же хочется решения конкретных проблем, то обычный запрос гугла entity component system hierarchy выдает кучку ссылок на различные англоязычные статьи, где разбирается проблема иерархии в ECS, можете ознакомиться с ними.
Целью моей статьи в том числе было показать, что у ECS как подхода есть свои проблемы и грабли, посему он не является "серебрянной пулей" или "волшебным фреймворком" и решение о выборе ECS в качестве подхода надо принимать с учётом этих недостатков. В Недостатках чётко сказано, что будут проблемы при попытке создавать иерархию и необходимости вызывать какую-то логику "здесь и сейчас". Их можно решить, если того требует задача, но это потребует времени.
Как было описано в Недостатках, ECS не особо хорошо дружит с иерархией, рекурсивной и реактивной логикой, так что если делать иерархию прямо в ECS, то придётся покостылить. Поэтому лично я рекомендую иерархию прикручивать немного сбоку в виде сервиса или ещё как-то.
Если говорить про связи, то все связи в ECS живут в компонентах в виде ссылок на другие сущности, то есть фактически об этом знают все системы и каждая может использовать её в своих интересах. Посему "Ссылочная целостность" целиком на плечах разработчика. Надо самому перед использованием проверять, что сущность в поле компонента живая и имеет необходимые данные.
Если бы мне пришлось решать такую задачу, то я бы, пожалуй, запилил систему, которая где-нибудь в конце кадра рекурсивно подчищает отмеченные маркером для удаления сущности-родители, но тут может быть много подводных камней.
1) В принципе так чаще всего и делают. По кнопке UI создаём сущность с компонентами, которые оповестят системы что им необходимо сделать, а дальше системы разберутся.
2) Если я правильно понял, то тут как раз проблема потенциальной рекурсии, которую я указал в недостатках ECS. Это, вцелом, можно решить как зацикливанием группы систем(как в статье описал), так и растянув логику на несколько кадров, если такое позволяется дизайном игры. Буду рад, если кто-то из опытных ECS-адептов подскажет как это ещё можно решить.
Вцелом, в обработке на следующий кадр нет ничего особо плохого, если это не запрещается геймдизайном(и не портит игру). Игрок всё равно этого не заметит.
Для большинства ситуаций он ок по производительности, но на большом количестве вызовов уже начинает вылезать и, если у тебя 100+ одинаковых объектов c вызовами `Fixed/Late/Update()`, то лучше переделать на менеджер, который будет вызывать у них кастомный ManualUpdate()
Такой паттерн хорошо подходит сложным играм, в которых есть очень много сущностей которые надо очень часто перебирать. ... ECS плохо подходит играм, в которых мало сущностей и их не надо часто перебирать (например 99% мобильного рынка).
Позволю себе не согласиться с таким утверждением. ECS в первую очередь подход к проектированию кода, а не паттерн для быстрого итерирования по тысячам сущностей. Главные достоинства ECS - слабая связность логики(а следовательно хорошая модульность, тестируемость) и комбинаторика свойств(проще сочетать в сущностях различные элементы логики). Благодаря этим достоинства ECS хорошо подходит как простым играм(99% мобильного рынка), так и сложным, особенно где много вариаций сущностей. И очень хорош для какого-нибудь гиперкэжа, где можно реюзать большую часть кода между проектами(при грамотном проектировании, ессесно).
Это да. После LeoECS количество годных ECS-фреймворков для шарпа начало увеличиваться: Actors, Morpeh, ME.ECS, DefaultECS... Такая тенденция не может не радовать.
Хочу заметить, что "с ECS беда" конкретно в DOTS, сам по себе ECS как паттерн штука хорошая и в большинстве фреймворков не требует танцев с бубном, но юнитеки ради гипер-производительность очень переусложнили фреймворк
Но это почти никак не влияет на основной тезис статьи: если проект не требует технологий UE5, то зачем тратить на разработку больше при практически одинаковом(зависит от специалистов) результате?
Позволю себе не согласиться.
В 18 лет я бросил универ на первом курсе. Программирование изучал исключительно в школе, да и то был паскаль. После универа поработал слесарем-ремонтником(почти сантехник) год и трактористом два, совсем не думая о программировании и даже не планируя им заниматься.
Но потом в мои 22 трактористу внезапно захотелось делать игры и для этого я начал изучать Java. Месяца два-три исключительно вникал в синтаксис и пытался понять как работают объектно-ориентированные языки, но таки с горем пополам написал крестики-нолики в консоли. Потом узнал про Unity. Увидел, что C# почти то же самое что и Java и быстренько трансформировался на шарпы.
Следующие пол года делал свою первую игру(двумерный космосим) на сколько хватало знаний, попутно пополняя знания C# с помощью Metanit и гугла. Пытался собрать комьюнити вокруг игры, но неудачно. И тут один знакомый программист сказал «Ты же умеешь кодить, целую игру запилил, зачем ты до сих пор возишься в тракторном масле? Ищи работу!». Ещё пол года искал первую работу, с третьей попытки таки нашёл место(правда не геймдев).
И вот, спустя три года, я опытный Middle+ Unity-разработчик с зарплатой в 6 раз больше, чем когда я начал изучать Java. Свои игры, к сожалению, больше не делаю, ибо с воображением и дизайном у меня туго, да и свободного времени не так много, но тем не менее получаю удовольствие от создания игр.
Но я абсолютно согласен с утверждением, что хорошая мотивация — наше ВСЁ. Если учиться разработке исключительно ради хорошего заработка и не получать от процесса удовольствие, то это вряд ли к чему приведёт.
Дорогой товарищ, вы наступили на достаточно частое заблуждение. Вы путаете два совершенно разных(хоть и близких) архитектурных подхода: Entity-Component-System(ECS, о котором эта статья) и Entity-Component(EC). Они хоть концептуально и близки, но совершенно разные на практике.
Почти все перечисленные вами варианты, в особенности Unity и UE4, по умолчанию предлагают именно EC-подход. Там есть условный GameObject/Actor(сущность) и есть его свойства(компоненты). Сама по себе сущность — абстракция, которая просто есть, а компоненты одновременно содержат и данные, и логику, которая обрабатывает эти самые данные. Собсно это допущение и порождает в итоге god-objects, тк так проще писать и проще думать. Когда у компонента напрямую вызывается Update() — это явный признак того, что перед нами именно EC.
Ключевая же особенность ECS — строгое отделение данных от их процессинга + линейный(конвейерный) способ обработки данных. Все иные ситуации, где перечисленных свойств не наблюдается, уже не являются ECS. Update(), в случае ECS, вызывается ИСКЛЮЧИТЕЛЬНО у систем, а внутри систем уже и происходит вся логическая магия. Системы, в свою очередь, не являются какими-либо хранителями состояния и, в идеале, не должны хранить каких-либо данных(но это допускается).
Unity в рамках DOTS предлагает разработчикам перейти с EC-подхода на чистый ECS, но и без DOTS для Unity(и C# в частности) уже предостаточно ECS-фреймворков, с которыми очень комфортно работать. Для C++ ECS-фреймворков тоже предостаточно, стоит только пройтись по гитхабу. Однако плюсовые фреймворки стоят немного в стороне от UE4, но уже появляются люди и проекты, которые хотят это исправить.
Движков, которые написаны изначально под использование ECS-подхода, можно пересчитать по пальцам, доступных общественности — на пальцах одной руки. Но они, к сожалению, пока только развиваются и еще далеки от идеала.
Надеюсь мне удалось развеять ваше заблуждение и вы таки попробуете ECS-подход на своих проектах. В него сложно влиться по началу, но стоит только вкусить этот божественный плод — больше не слезешь :)
Сама по себе архитектура никак не влияет на количество лапши, которую нужно писать. А вот конкретный фреймворк — уже влияет.
Svetlo ECS — ИМХО, рекордсмен по количеству лапши
Unity ECS — требует уже немного меньше необходимой лапши(хотя это еще хз)
Entitas — еще меньше лапши, но в обмен на кодогенерацию
Однако есть и всякие опенсорсные альтернативы, которые стараются делать максимально простой и понятный API — LeoECS и Morpeh. Вот в них количество кода будет на несколько строк больше, чем в аналогичном коде на монобехах, зато взамен они дают лучшую модульность, тестируемость и расширяемость, по сравнению с любыми вариантами на монобехах.
Этот материал обзорный и предназначен скорее для популяризации ECS, чем для решения конкретных проблем. Конечно люди удаляют данные и, если того требует задача, заботятся о сиротах и висячих ссылках, но какого-то автоматизированного или единственно правильного решения задач подобного рода нету, ибо каждая задача требует своего решения исходя из своей специфики и особенностей используемого подхода.
Если же хочется решения конкретных проблем, то обычный запрос гугла
entity component system hierarchy
выдает кучку ссылок на различные англоязычные статьи, где разбирается проблема иерархии в ECS, можете ознакомиться с ними.Целью моей статьи в том числе было показать, что у ECS как подхода есть свои проблемы и грабли, посему он не является "серебрянной пулей" или "волшебным фреймворком" и решение о выборе ECS в качестве подхода надо принимать с учётом этих недостатков. В Недостатках чётко сказано, что будут проблемы при попытке создавать иерархию и необходимости вызывать какую-то логику "здесь и сейчас". Их можно решить, если того требует задача, но это потребует времени.
Как было описано в Недостатках, ECS не особо хорошо дружит с иерархией, рекурсивной и реактивной логикой, так что если делать иерархию прямо в ECS, то придётся покостылить. Поэтому лично я рекомендую иерархию прикручивать немного сбоку в виде сервиса или ещё как-то.
Если говорить про связи, то все связи в ECS живут в компонентах в виде ссылок на другие сущности, то есть фактически об этом знают все системы и каждая может использовать её в своих интересах. Посему "Ссылочная целостность" целиком на плечах разработчика. Надо самому перед использованием проверять, что сущность в поле компонента живая и имеет необходимые данные.
Если бы мне пришлось решать такую задачу, то я бы, пожалуй, запилил систему, которая где-нибудь в конце кадра рекурсивно подчищает отмеченные маркером для удаления сущности-родители, но тут может быть много подводных камней.
Большое спасибо за такую оценку :)
Рад слышать такие слова :)
1) В принципе так чаще всего и делают. По кнопке UI создаём сущность с компонентами, которые оповестят системы что им необходимо сделать, а дальше системы разберутся.
2) Если я правильно понял, то тут как раз проблема потенциальной рекурсии, которую я указал в недостатках ECS. Это, вцелом, можно решить как зацикливанием группы систем(как в статье описал), так и растянув логику на несколько кадров, если такое позволяется дизайном игры. Буду рад, если кто-то из опытных ECS-адептов подскажет как это ещё можно решить.
Вцелом, в обработке на следующий кадр нет ничего особо плохого, если это не запрещается геймдизайном(и не портит игру). Игрок всё равно этого не заметит.
Как психологически такой темп и удары судьбы выдерживаешь?
Для большинства ситуаций он ок по производительности, но на большом количестве вызовов уже начинает вылезать и, если у тебя 100+ одинаковых объектов c вызовами `Fixed/Late/Update()`, то лучше переделать на менеджер, который будет вызывать у них кастомный
ManualUpdate()
Юнитехи сами писали статейку про это
С этим утверждением склонен согласиться :)
Под маленькими играми просто представлял какой-нибудь гиперкэж, где от ECS всё таки есть польза
Позволю себе не согласиться с таким утверждением. ECS в первую очередь подход к проектированию кода, а не паттерн для быстрого итерирования по тысячам сущностей. Главные достоинства ECS - слабая связность логики(а следовательно хорошая модульность, тестируемость) и комбинаторика свойств(проще сочетать в сущностях различные элементы логики). Благодаря этим достоинства ECS хорошо подходит как простым играм(99% мобильного рынка), так и сложным, особенно где много вариаций сущностей. И очень хорош для какого-нибудь гиперкэжа, где можно реюзать большую часть кода между проектами(при грамотном проектировании, ессесно).
PS Есличто речь именно про ECS, а не DOTS
Это да. После LeoECS количество годных ECS-фреймворков для шарпа начало увеличиваться: Actors, Morpeh, ME.ECS, DefaultECS... Такая тенденция не может не радовать.
Хочу заметить, что "с ECS беда" конкретно в DOTS, сам по себе ECS как паттерн штука хорошая и в большинстве фреймворков не требует танцев с бубном, но юнитеки ради гипер-производительность очень переусложнили фреймворк
Но это почти никак не влияет на основной тезис статьи: если проект не требует технологий UE5, то зачем тратить на разработку больше при практически одинаковом(зависит от специалистов) результате?
В 18 лет я бросил универ на первом курсе. Программирование изучал исключительно в школе, да и то был паскаль. После универа поработал слесарем-ремонтником(почти сантехник) год и трактористом два, совсем не думая о программировании и даже не планируя им заниматься.
Но потом в мои 22 трактористу внезапно захотелось делать игры и для этого я начал изучать Java. Месяца два-три исключительно вникал в синтаксис и пытался понять как работают объектно-ориентированные языки, но таки с горем пополам написал крестики-нолики в консоли. Потом узнал про Unity. Увидел, что C# почти то же самое что и Java и быстренько трансформировался на шарпы.
Следующие пол года делал свою первую игру(двумерный космосим) на сколько хватало знаний, попутно пополняя знания C# с помощью Metanit и гугла. Пытался собрать комьюнити вокруг игры, но неудачно. И тут один знакомый программист сказал «Ты же умеешь кодить, целую игру запилил, зачем ты до сих пор возишься в тракторном масле? Ищи работу!». Ещё пол года искал первую работу, с третьей попытки таки нашёл место(правда не геймдев).
И вот, спустя три года, я опытный Middle+ Unity-разработчик с зарплатой в 6 раз больше, чем когда я начал изучать Java. Свои игры, к сожалению, больше не делаю, ибо с воображением и дизайном у меня туго, да и свободного времени не так много, но тем не менее получаю удовольствие от создания игр.
Но я абсолютно согласен с утверждением, что хорошая мотивация — наше ВСЁ. Если учиться разработке исключительно ради хорошего заработка и не получать от процесса удовольствие, то это вряд ли к чему приведёт.
Почти все перечисленные вами варианты, в особенности Unity и UE4, по умолчанию предлагают именно EC-подход. Там есть условный GameObject/Actor(сущность) и есть его свойства(компоненты). Сама по себе сущность — абстракция, которая просто есть, а компоненты одновременно содержат и данные, и логику, которая обрабатывает эти самые данные. Собсно это допущение и порождает в итоге god-objects, тк так проще писать и проще думать. Когда у компонента напрямую вызывается Update() — это явный признак того, что перед нами именно EC.
Ключевая же особенность ECS — строгое отделение данных от их процессинга + линейный(конвейерный) способ обработки данных. Все иные ситуации, где перечисленных свойств не наблюдается, уже не являются ECS. Update(), в случае ECS, вызывается ИСКЛЮЧИТЕЛЬНО у систем, а внутри систем уже и происходит вся логическая магия. Системы, в свою очередь, не являются какими-либо хранителями состояния и, в идеале, не должны хранить каких-либо данных(но это допускается).
Unity в рамках DOTS предлагает разработчикам перейти с EC-подхода на чистый ECS, но и без DOTS для Unity(и C# в частности) уже предостаточно ECS-фреймворков, с которыми очень комфортно работать. Для C++ ECS-фреймворков тоже предостаточно, стоит только пройтись по гитхабу. Однако плюсовые фреймворки стоят немного в стороне от UE4, но уже появляются люди и проекты, которые хотят это исправить.
Движков, которые написаны изначально под использование ECS-подхода, можно пересчитать по пальцам, доступных общественности — на пальцах одной руки. Но они, к сожалению, пока только развиваются и еще далеки от идеала.
Надеюсь мне удалось развеять ваше заблуждение и вы таки попробуете ECS-подход на своих проектах. В него сложно влиться по началу, но стоит только вкусить этот божественный плод — больше не слезешь :)
Svetlo ECS — ИМХО, рекордсмен по количеству лапши
Unity ECS — требует уже немного меньше необходимой лапши(хотя это еще хз)
Entitas — еще меньше лапши, но в обмен на кодогенерацию
Однако есть и всякие опенсорсные альтернативы, которые стараются делать максимально простой и понятный API — LeoECS и Morpeh. Вот в них количество кода будет на несколько строк больше, чем в аналогичном коде на монобехах, зато взамен они дают лучшую модульность, тестируемость и расширяемость, по сравнению с любыми вариантами на монобехах.