Статью можно дополнить только через привлечение модераторов, поэтому просто отпишу здесь:
Крайне рекомендую заценить ещё эту статью на хабре. В ней можно шаг за шагом проследить каким образом разработчик одного из самых ранних ECS-фреймворков от ООП пришёл к ECS. Очень интересное наблюдение.
Ну недостатком оно становится, когда вне зависимости от ситуации у тебя всегда один порядок логики. В ООП ты можешь для конкретной ситуации поменять два вызова местами, не меняя порядок в остальных вызовах, а в ECS так не выйдет.
Заценил как chromealex реализовал иерархию в своём ECS. Мне очень понравилось, советую тоже заценить.
Если вкратце, то всё крутится вокруг StaticUtils, в которых лежит техническая логика и через который мы манипулируем иерархией. Технические компоненты со списком детей и ссылкой на родителя. Реактивная связь с ядром фреймворка, чтобы при удалении сущности удалять всех её детей.
Этот материал обзорный и предназначен скорее для популяризации 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, крайне рекомендую к ознакомлению - https://habr.com/ru/articles/742376/
Отличная статья! Огромное спасибо!
Задумка прикольная :)
Ещё можно Soulseek попробовать: древняя p2p сеть по обмену музыкой, где чего только нету
Скорее всего именно в этом все дело
Статью можно дополнить только через привлечение модераторов, поэтому просто отпишу здесь:
Крайне рекомендую заценить ещё эту статью на хабре. В ней можно шаг за шагом проследить каким образом разработчик одного из самых ранних ECS-фреймворков от ООП пришёл к ECS. Очень интересное наблюдение.
Я именно так и пришёл в IT, правда, к моему сожалению, не всегда делаю игры
Зачем туторы, когда есть экзамплы?
https://github.com/scellecs/morpeh.examples.pong
https://github.com/scellecs/morpeh.examples.tanks
Ну недостатком оно становится, когда вне зависимости от ситуации у тебя всегда один порядок логики. В ООП ты можешь для конкретной ситуации поменять два вызова местами, не меняя порядок в остальных вызовах, а в ECS так не выйдет.
Заценил как chromealex реализовал иерархию в своём ECS. Мне очень понравилось, советую тоже заценить.
Если вкратце, то всё крутится вокруг StaticUtils, в которых лежит техническая логика и через который мы манипулируем иерархией. Технические компоненты со списком детей и ссылкой на родителя. Реактивная связь с ядром фреймворка, чтобы при удалении сущности удалять всех её детей.
Этот материал обзорный и предназначен скорее для популяризации 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... Такая тенденция не может не радовать.