Unity и .NET: что дальше?

ALEXANDRE MUTEL / UNITY TECHNOLOGIESContributor
May 18, 2022|15 Мин
Unity и .NET: что дальше?
Эта веб-страница была переведена с помощью машинного перевода для вашего удобства. Мы не можем гарантировать точность или надежность переведенного контента. Если у вас есть вопросы о точности переведенного контента, обращайтесь к официальной английской версии веб-страницы.

Недавно мы запустили многолетнюю инициативу, призванную помочь вам быстрее писать более производительный код и обеспечить долгосрочную стабильность и совместимость. Читайте дальше, чтобы узнать, что мы делаем для обновления базовой технологической инфраструктуры ваших скриптов.

Экосистема .NET динамично развивается во многих полезных направлениях, и мы хотим как можно скорее донести эти улучшения до вас. Наша внутренняя группа разработчиков .NET постоянно работает над улучшением интеграции с .NET, включая новые функции C# и .NET Standard 2.1 . Но, основываясь на ваших отзывах, мы недавно активизировали работу, чтобы улучшить ваш опыт как разработчика в целом.

В этом посте в блоге представлены проблемы, над которыми мы работаем. Мы также обсуждали эту тему на Unity Dev Summit в рамках GDC 2022. Полную запись сессии можно посмотреть здесь .

Эволюция .NET и Unity

История началась 17 лет назад, когда наш технический директор начал использовать среду выполнения Mono .NET с C#. Unity отдала предпочтение C# из-за его простоты в сочетании с JIT-компилятором (just-in-time), который преобразует ваш код C# в относительно эффективный нативный код. Оставшиеся и значительно большие части движка Unity были разработаны с использованием C++ для обеспечения сбалансированной и контролируемой производительности.

В течение многих лет Unity работала на основе определённой модификации среды выполнения Mono .NET и языка C# (версия 2.0). За это время мы добавили поддержку дополнительных платформ. Мы также разработали собственный компилятор и среду выполнения IL2CPP, что позволяет вам ориентироваться на iOS и некоторые консольные платформы.

Тем временем, общая экосистема Microsoft .NET претерпела изменения, появились новые системы лицензирования и поддержка платформ, отличных от Windows. Эта эволюция позволила нам обновить среду выполнения Unity .NET Mono в 2018 году и использовать более современные версии языка C# (7.0+). В том же году мы также выпустили первую версию компилятора Burst , став пионерами в создании быстрого нативного кода, генерируемого для подмножества языка C#. Этот прорыв позволил Unity представить себе мир, в котором мы могли бы расширить использование C# в других критически важных сегментах движка, не разрабатывая эти части на C++, что привело к разработке среды выполнения DOTS .

В Unity 2020 LTS и Unity 2021 LTS были представлены новые версии языка C# и новые API для .NET. Параллельно мы наблюдаем значительное повышение производительности в экосистеме .NET, а также более удобную среду разработки благодаря внедрению csproj в стиле SDK и процветающей экосистеме NuGet.

Что нам нужно сделать

В результате этой длительной эволюции платформа Unity включает в себя очень большой код на C++, который напрямую взаимодействует с объектами .NET, используя определенные предположения, унаследованные от среды выполнения Mono .NET. Эти методы больше не являются актуальными или эффективными для среды выполнения .NET (Core).

Кроме того, существует сложный собственный конвейер компиляции, привязанный к редактору Unity , который не зависит от MSBuild и, следовательно, не может в полной мере использовать все стандартные функции.

В течение последних нескольких лет мы также общались со многими из вас, как в ходе интервью, так и на форуме Unity , чтобы понять, что мы можем улучшить, чтобы еще больше способствовать вашему успеху. Как нам стало известно, вы хотите использовать новейший язык C#, среду выполнения .NET и сторонний код C# из NuGet. Что касается использования платформы Unity , вы сказали, что хотите максимально эффективно использовать целевое оборудование с помощью высококачественных инструментов тестирования, отладки и профилирования на C#, а также хорошей интеграции между стандартным API .NET и API Unity . Как программист на C# в Unity , вы хотите использовать инструменты Unity , которые бесперебойно взаимодействуют с остальными вашими инструментами и позволяют быстро вносить изменения, чтобы добиться лучшей в своем классе производительности во время выполнения.

На достижение этой цели нам потребуется несколько лет. Мы будем держать вас в курсе технических проблем, с которыми мы сталкиваемся на этом пути, регулярно публикуя обновления в блоге и на форуме.

Как мы это сделаем?

Первым шагом в рамках этой инициативы стало объединение всех внутренних сотрудников, увлеченных C# и .NET в Unity , для формирования технической группы по C#/.NET, которая будет руководить этой работой.

Мы хотим строить свою систему на основе экосистемы .NET, а не разрабатывать собственные решения. Чтобы вы могли воспользоваться преимуществами повышения производительности и эффективности, которые обеспечивают новейшие .NET SDK/Runtime и MSBuild, мы хотим перейти с Mono .NET Runtime на CoreCLR, современный .NET (Core) Runtime.

Эта инициатива также предлагает инновации за пределами существующей вселенной .NET с целью ускорения циклов итераций .NET для ваших скриптов на C#. Мы будем работать над объединением решений JIT и AOT (ahead-of-time) – IL2CPP и Burst – для достижения оптимального баланса между эффективностью компиляции и качеством генерации кода.

Внешние партнеры, такие как Microsoft и JetBrains, сотрудничают с нами, чтобы гарантировать, что разработчики Unity используют новейшие технологии .NET. Мы также наращиваем наше участие в сообществах разработчиков открытого программного обеспечения. Мы разделим эту задачу на несколько этапов. Посмотрим, что будет дальше.

Над чем мы работаем в 2022 году

В этом году команды планируют работать на следующих трассах.

Инфографика, иллюстрирующая основные принципы работы Unity Developer Experience.
Рабочий процесс разработки на C#

Время, затрачиваемое на итерации, остается для нас главным приоритетом, поскольку мы знаем, что вы хотите максимально эффективно использовать свое время. Вот несколько примеров того, что мы делаем для улучшения ситуации.

  • В рамках конвейера компиляции мы сокращаем время, затрачиваемое на постобработку IL-кода, которая отвечает за изменение скомпилированных сборок .NET после компиляции вашего кода C#. Теперь мы используем постоянно работающий процесс для выполнения постобработки IL-кода после этапа компиляции, что позволяет сэкономить несколько сотен миллисекунд.
  • В связи с более частым использованием компилятора Burst мы повышаем точность обнаружения изменений в коде с помощью алгоритма транзитивного хеширования. Это позволяет нам быстрее определить, какой код Burstable нам нужно скомпилировать. Мы работаем над тем, чтобы перенести компилятор Burst в отдельный процесс, чтобы он мог компилировать ваш код быстрее благодаря запуску в отдельном исполняемом файле .NET 6.0.
  • Мы также улучшаем перезагрузку домена, совершенствуя данные рефлексии, создаваемые в фоновом режиме при использовании TypeCache .
  • Мы собираемся добавить тесты и валидацию для более эффективного отслеживания регрессии во время итераций для пакетов и шаблонов проектов.

Для перехода на MSBuild первым шагом является отделение нашего конвейера компиляции от редактора Unity и перенос его в отдельный процесс. Это сложная операция, поскольку нам нужно распутать многолетний устаревший код, состоящий из тысяч строк кода на C++ и C#, чтобы достичь этой цели, сохраняя при этом обратную совместимость. С вашей точки зрения, изменений не будет, но это проложит нам путь к MSBuild и упростит сопровождение проекта.

Мы также собираемся улучшить работу с отладчиком C# в IDE с помощью Burst , внедрив режим, который будет автоматически переключать отладчик в управляемую отладку при установке точки останова на участке кода, выполняемом с помощью Burst. Это означает, что вам не придётся вручную удалять атрибут [BurstCompile] в отлаживаемом фрагменте кода.

Модернизация среды выполнения .NET

Работа по миграции на среду выполнения .NET CoreCLR уже началась, и это очень сложный процесс. Для успешного осуществления миграции мы хотели бы решать эту проблему постепенно и обеспечить выпуск отдельных компонентов таким образом, чтобы сохранить стабильность существующих проектов Unity .

Таким образом, мы планируем осуществить эту миграцию в несколько этапов:

  • Во-первых, мы обеспечим поддержку .NET CoreCLR для автономных проигрывателей на настольных платформах. Вы сможете выбрать эту среду выполнения в настройках плеера наряду с существующими бэкэндами Mono и IL2CPP. Этот первый этап должен помочь нам перенести основную часть движка Unity (которая значительно меньше, чем часть редактора) и, будем надеяться, решит значительную часть технических проблем, связанных с этой миграцией. Вы по-прежнему будете получать доступ к среде выполнения .NET через API.NET Standard 2.1, и мы планируем выпустить эту новую среду выполнения в течение 2023 года.
  • Во-вторых, мы перенесём редактор Unity на .NET CoreCLR и одновременно удалим поддержку среды выполнения .NET Mono . На втором этапе мы проверим, как будем перезагружать ваши скрипты в редакторе без использования AppDomains, и завершим переход на .NET CoreCLR. Это также будет включать в себя обновление IL2CPP для поддержки базовых библиотек классов из репозитория dotnet/runtime. Наконец-то вы получите доступ ко всему API.NET 7.x или 8.0. Мы надеемся выпустить этот новый редактор в течение 2024 года.
Модернизация среды выполнения Unity

Поддержка .NET Standard 2.1 в Unity 2021 LTS позволяет нам начать модернизацию среды выполнения Unity различными способами. В настоящее время мы работаем над двумя улучшениями.

Улучшение модели программирования async/await . Async/await — это фундаментальный подход в программировании, используемый для написания игрового кода, который должен дожидаться завершения асинхронной операции, не блокируя при этом основной цикл движка.

В 2011 году, до того как async/await стал широко распространен в .NET, Unity представила асинхронные операции с использованием сопрограмм на основе итераторов, но этот подход несовместим с async/await и может быть менее эффективным. Тем временем, в .NET Standard 2.1 улучшилась поддержка async/await в C# и .NET за счет внедрения более эффективной обработки операций async/await с помощью ValueTask , а также за счет возможности использования собственной системы, подобной задачам, с помощью AsyncMethodBuilder.

Теперь мы можем использовать эти улучшения, поэтому работаем над тем, чтобы включить использование async/await с существующими асинхронными операциями в Unity (например, ожидание следующего кадра или ожидание завершения UnityWebRequest). В качестве первого шага мы улучшаем поддержку отмены ожидающих асинхронных задач при уничтожении объекта MonoBehavior или при выходе из режима воспроизведения с помощью токенов отмены . Мы также тесно сотрудничаем с нашими крупнейшими участниками сообщества, такими как автор UniTask , чтобы обеспечить им возможность использовать эти новые функции.

Сокращение выделения и копирования памяти за счет использования Span. Поскольку Unity — это движок на C++ с уровнем написания скриптов на C#, между ними происходит большой обмен данными. Это может быть неэффективно, поскольку часто требует либо копирования данных туда и обратно, либо выделения новых управляемых объектов.

Параметр Span был введен в C# 7.2 для улучшения подобных сценариев и доступен по умолчанию в .NET Standard 2.1. В последние годы вы, возможно, слышали или читали о многих значительных улучшениях производительности среды выполнения .NET благодаря Span (подробности улучшений см. в .NET Core 2.1 , .NET Core 3.0 , .NET 6 , .NET 6 ). Мы хотим использовать его в Unity, поскольку это поможет сократить выделение памяти и, следовательно, приостановку сборки мусора, а также улучшит общую производительность многих API.

Присоединяйтесь к нам в этом путешествии!

Мы надеемся, что вы все так же рады этим изменениям и новым функциям, как и мы.

Поделитесь своим мнением о наших планах на форуме . Мы также будем регулярно обновлять раздел «Инженерные разработки» в дорожной карте платформы Unity , и вы сможете делиться с нами своими пожеланиями по функциям и предложениями по приоритезации там.

Примечание редактора: Данная статья в последний раз обновлялась в феврале 2023 года.