Переход на ECS.
Разработчики Unity знали обо всех этих проблемах и уперевшись в потолок доступных инструментов ввели новый подход для разработки — ECS или Entity-Component-System.
ECS более не полагается на managed-природу C#. Здесь мы сами выделяем и освобождаем память, а функции-джобы компилируем с помощью специального компилятора чтобы они выполнялись на скоростях сравнимых с C++. Также мы получили возможность выполнять такие функции многопоточно и делать это очень эффективно в виду того как в ECS организуется работа с памятью.
Как я говорил ранее, в обычных managed-классах все данные инстанса выделяются в памяти хаотично. Мы не можем просто обработать все координаты 1000 зерлингов — под капотом с каждым из них будет индивидуальная работа. А значит мы не можем эффективно это распаралелить.
ECS вводит понятия Entity и Component — Entity это некая сущность, «якорь» для данных, а Component это собственно какие-то данные. Например Entity это будет наш зерлинг, и он будет иметь компоненты — Position, Rotation, Health, Attack и тд. В таком случае мы получим архетип — Enity который имеет конкретный перечень компонентов. И данные этих компонентов в памяти займут один конкретный блок, то есть все позиции всех зерлингов будут лежать одним непрерывным блоком! Не нужно будет отдельно искать где там runtime выделил место под очередную пачку координат! Всё в одном месте от начала и до конца.
И мы мы можем взять эту пачку данных, засунуть в процессор и запустить параллельную многопоточную обработку их всех сразу.
Для обработки и изменения данных в ECS используются системы — System, та самая «S» из ECS. Системы используют ограниченный API, позволяя применять Burst-компиляцию и превращать их в настоящих многопоточных монстров обработки.
Главная проблема ECS — вы теряете удобную иерархию сцены из GameObject’ов и в целом процесс разработки заметно усложняется. Также вам становятся недоступны многие API самого юнити. Однако, вы можете строить «мосты» между managed и ECS мирами. И такие мосты часто необходимы так как не всё можно сделать из ECS.
Но преимущества в определенных ситуациях перевешивают все недостатки, особенно когда вы наконец получаете бесшовный бесконечный мир без единого статтера )
Ещё одна особенность ECS-мира — в нем не доступна классическая Unity-физика на PhysX.
А значит у вас нет удобного способа через инспектор расставлять коллайдеры, мы теряем все предзаготовленные инструменты вроде Vehicle-физики и CharacterController’а.
В замен мы получаем альтернативную ECS-Unity-физику которая работает на много потоков, но имеет множество нюансов. Инструменты вроде CharacterController’а и Vehicle-физики уже имеются, но находятся в ранних бетах и плохо описаны. А коллайдеры расставлять приходится программно или же добавить фазу «запекания» моделек. Мы с помощью редактора префаба расставляем обычные managed-коллайдеры в привычном UI, но при сохраненнии запускается специальный скрипт который заменяет все managed-обертки на настоящие ECS-Physics-Colliers.
Есть также опция использовать Havok, но с недавнего времени лицензию на него нужно покупать самостоятельно, а это 50 000 долларов )
В общем, резюмируя всё выше сказанное: в какой-то момент из-за статтеров я был готов отказаться от Unity и пересесть на Unreal Engine и даже рассматривал движки на Rust, но погружение в ECS решило мои проблемы и вернуло мне веру в успех оставаясь на Unity.
#devblog
Разработчики Unity знали обо всех этих проблемах и уперевшись в потолок доступных инструментов ввели новый подход для разработки — ECS или Entity-Component-System.
ECS более не полагается на managed-природу C#. Здесь мы сами выделяем и освобождаем память, а функции-джобы компилируем с помощью специального компилятора чтобы они выполнялись на скоростях сравнимых с C++. Также мы получили возможность выполнять такие функции многопоточно и делать это очень эффективно в виду того как в ECS организуется работа с памятью.
Как я говорил ранее, в обычных managed-классах все данные инстанса выделяются в памяти хаотично. Мы не можем просто обработать все координаты 1000 зерлингов — под капотом с каждым из них будет индивидуальная работа. А значит мы не можем эффективно это распаралелить.
ECS вводит понятия Entity и Component — Entity это некая сущность, «якорь» для данных, а Component это собственно какие-то данные. Например Entity это будет наш зерлинг, и он будет иметь компоненты — Position, Rotation, Health, Attack и тд. В таком случае мы получим архетип — Enity который имеет конкретный перечень компонентов. И данные этих компонентов в памяти займут один конкретный блок, то есть все позиции всех зерлингов будут лежать одним непрерывным блоком! Не нужно будет отдельно искать где там runtime выделил место под очередную пачку координат! Всё в одном месте от начала и до конца.
И мы мы можем взять эту пачку данных, засунуть в процессор и запустить параллельную многопоточную обработку их всех сразу.
Для обработки и изменения данных в ECS используются системы — System, та самая «S» из ECS. Системы используют ограниченный API, позволяя применять Burst-компиляцию и превращать их в настоящих многопоточных монстров обработки.
Главная проблема ECS — вы теряете удобную иерархию сцены из GameObject’ов и в целом процесс разработки заметно усложняется. Также вам становятся недоступны многие API самого юнити. Однако, вы можете строить «мосты» между managed и ECS мирами. И такие мосты часто необходимы так как не всё можно сделать из ECS.
Но преимущества в определенных ситуациях перевешивают все недостатки, особенно когда вы наконец получаете бесшовный бесконечный мир без единого статтера )
Ещё одна особенность ECS-мира — в нем не доступна классическая Unity-физика на PhysX.
А значит у вас нет удобного способа через инспектор расставлять коллайдеры, мы теряем все предзаготовленные инструменты вроде Vehicle-физики и CharacterController’а.
В замен мы получаем альтернативную ECS-Unity-физику которая работает на много потоков, но имеет множество нюансов. Инструменты вроде CharacterController’а и Vehicle-физики уже имеются, но находятся в ранних бетах и плохо описаны. А коллайдеры расставлять приходится программно или же добавить фазу «запекания» моделек. Мы с помощью редактора префаба расставляем обычные managed-коллайдеры в привычном UI, но при сохраненнии запускается специальный скрипт который заменяет все managed-обертки на настоящие ECS-Physics-Colliers.
Есть также опция использовать Havok, но с недавнего времени лицензию на него нужно покупать самостоятельно, а это 50 000 долларов )
В общем, резюмируя всё выше сказанное: в какой-то момент из-за статтеров я был готов отказаться от Unity и пересесть на Unreal Engine и даже рассматривал движки на Rust, но погружение в ECS решило мои проблемы и вернуло мне веру в успех оставаясь на Unity.
#devblog
👍1
Curved World
Если мир бесконечный, встаёт вопрос что делать с линией горизонта.
Скайбокс не нарисуешь, реальную «прогрузку» далеко не сделаешь — это всё ресурсы которых не так много, учитывая что я мечу также в порт на мобильные устройства. Остаётся только добавить туман как в Silent Hill )
И как-то вдруг мне пришла в голову идея сделать эффект «круглой планеты» — загибать игровой мир за линию горизонта. Позже я узнал что оказывается «в народе» этот эффект больше всего ассоциируется с Animal Crossing и это мне позже пригодится.
Первые попытки реализовать этот эффект я принял ещё когда проект был ориентирован на Web-технологии. Да, я пытался собрать прототип на React+Three.js+Colyseus и оно в принципе работало — можно было открыть сайт хоть с телефона, хоть с компа, хоть через встроенный браузер VR-шлема и попасть в игру. Причем даже работал proximity-voice-chat посредством WebRTC. Но сейчас не об этом.
Так как в браузере ресурсов крайне мало, а я тогда был уж совсем не гейм-девелопер чтобы писать кастомные шейдеры — я подошел к решению «в лоб». Так как мир уже разделен на тайлы — мы можем просто эти тайлы смещать по Y-координате пропорционально расстоянию от игрока. И это работало!
Однако, при подъеме на высокие горы вся магия «рассыпалась». Становились видны эти поднимающиеся-опускающиеся «островки» и их резкие квадратные границы.
В целом, в этом тоже был свой шарм и игру можно было продолжать делать именно с этим эффектом.
Проблема крылась в принципе размещения пропов: из-за того что у меня была потребность привязывать каждый проп к родителю-тайлу чтобы двигать его по высоте вместе с ним — я не мог использовать GPU-инстанцирование, так как оно не поддерживает parent-transform, все координаты инстансов нужно передать «как есть».
К этому времени эксперименты с ускорением рендеринга увели меня в сторону собственного шейдера — я перешел на цвета запеченные в вершины, а стандартный Unity/Lit такое не умеет. В собственный шейдер можно было добавить «честный» curved-world — смещать именно вершины через vertex-shader.
Эффект превзошел все мои ожидания! Если раньше было видно как куски уровня на горизонте двигаются ввер-вниз, то теперь весь уровень искривзялся и загибался за горизонт максимально плавно. Деревья и здания «выползали» из-за горизонта давая ощущение исследования круглой планеты.
Следующий челлендж был в том как заставить облака огибать наш круглый мир.
Но перед этим нужно было в принципе как-то сделать интересные динамичный облака )
Об этом в другой раз.
#devblog
Если мир бесконечный, встаёт вопрос что делать с линией горизонта.
Скайбокс не нарисуешь, реальную «прогрузку» далеко не сделаешь — это всё ресурсы которых не так много, учитывая что я мечу также в порт на мобильные устройства. Остаётся только добавить туман как в Silent Hill )
И как-то вдруг мне пришла в голову идея сделать эффект «круглой планеты» — загибать игровой мир за линию горизонта. Позже я узнал что оказывается «в народе» этот эффект больше всего ассоциируется с Animal Crossing и это мне позже пригодится.
Первые попытки реализовать этот эффект я принял ещё когда проект был ориентирован на Web-технологии. Да, я пытался собрать прототип на React+Three.js+Colyseus и оно в принципе работало — можно было открыть сайт хоть с телефона, хоть с компа, хоть через встроенный браузер VR-шлема и попасть в игру. Причем даже работал proximity-voice-chat посредством WebRTC. Но сейчас не об этом.
Так как в браузере ресурсов крайне мало, а я тогда был уж совсем не гейм-девелопер чтобы писать кастомные шейдеры — я подошел к решению «в лоб». Так как мир уже разделен на тайлы — мы можем просто эти тайлы смещать по Y-координате пропорционально расстоянию от игрока. И это работало!
Однако, при подъеме на высокие горы вся магия «рассыпалась». Становились видны эти поднимающиеся-опускающиеся «островки» и их резкие квадратные границы.
В целом, в этом тоже был свой шарм и игру можно было продолжать делать именно с этим эффектом.
Проблема крылась в принципе размещения пропов: из-за того что у меня была потребность привязывать каждый проп к родителю-тайлу чтобы двигать его по высоте вместе с ним — я не мог использовать GPU-инстанцирование, так как оно не поддерживает parent-transform, все координаты инстансов нужно передать «как есть».
К этому времени эксперименты с ускорением рендеринга увели меня в сторону собственного шейдера — я перешел на цвета запеченные в вершины, а стандартный Unity/Lit такое не умеет. В собственный шейдер можно было добавить «честный» curved-world — смещать именно вершины через vertex-shader.
Эффект превзошел все мои ожидания! Если раньше было видно как куски уровня на горизонте двигаются ввер-вниз, то теперь весь уровень искривзялся и загибался за горизонт максимально плавно. Деревья и здания «выползали» из-за горизонта давая ощущение исследования круглой планеты.
Следующий челлендж был в том как заставить облака огибать наш круглый мир.
Но перед этим нужно было в принципе как-то сделать интересные динамичный облака )
Об этом в другой раз.
#devblog
🔥3