Unity et .NET, quelle est la suite ?

ALEXANDRE MUTEL / UNITY TECHNOLOGIESContributor
May 18, 2022|15 Min
Unity et .NET, quelle est la suite ?
Cette page a été traduite automatiquement pour faciliter votre expérience. Nous ne pouvons pas garantir l'exactitude ou la fiabilité du contenu traduit. Si vous avez des doutes quant à la qualité de cette traduction, reportez-vous à la version anglaise de la page web.

Nous avons récemment lancé une initiative pluriannuelle pour vous aider à écrire du code plus performant plus rapidement et à offrir une stabilité et une compatibilité à long terme. Lisez la suite pour découvrir ce que nous faisons pour mettre à jour la pile technologique fondamentale derrière vos scripts.

L'écosystème .NET évolue dynamiquement de plusieurs façons bénéfiques, et nous voulons vous apporter ces améliorations dès que nous le pouvons. Notre groupe .NET Tech interne travaille à l'amélioration continue de notre intégration .NET, y compris les nouvelles fonctionnalités C# et la norme .NET 2.1. Mais nous avons récemment passé à la vitesse supérieure pour améliorer votre expérience de développeur dans tous les domaines, en fonction de vos commentaires.

Cet article de blog présente les questions sur lesquelles nous travaillons. Nous avons également discuté de ce sujet lors du Sommet Unity Dev à GDC 2022. Vous pouvez regarder la session complète ici.

L'évolution de .NET et Unity

L'histoire commence il y a 17 ans, lorsque notre directeur technique a commencé à exploiter le runtime Mono .NET avec C#. Unity privilégiait le C# en raison de sa simplicité, associée à un compilateur JIT (juste à temps) qui traduit votre C# en code natif relativement efficace. Les parties restantes et beaucoup plus grandes du moteur Unity ont été développées en utilisant le C++ afin de fournir des performances bien équilibrées et contrôlées.

Depuis de nombreuses années, Unity fonctionnait avec un fork spécifique du runtime Mono .NET et du langage C# (2.0). Au cours de cette période, nous avons ajouté le support de plateformes supplémentaires. Nous avons également développé notre propre compilateur et runtime, IL2CPP, pour vous permettre de cibler iOS et certaines plateformes consoles.

Entre-temps, l'écosystème global de Microsoft .NET a évolué, avec de nouvelles licences et le support des plateformes non Windows. Cette évolution nous a permis de mettre à niveau l'Unity .NET Mono Runtime en 2018 et d'adopter des versions en langage C# plus modernes (7.0+). La même année, nous avons également publié la première version du compilateur Burst, pionnier du code natif rapide généré pour un sous-ensemble du langage C#. Cette percée a permis à Unity d'envisager un monde où nous pourrions étendre l'utilisation du C# dans les autres segments critiques du moteur sans avoir à développer ces pièces en C++, conduisant au développement du runtime DOTS.

Unity 2020 LTS et Unity 2021 LTS ont apporté de nouvelles versions en langage C# et de nouvelles API .NET. En parallèle, nous avons assisté à d'énormes améliorations des performances de l'écosystème .NET, ainsi qu'à un environnement de développement plus convivial avec l'introduction de csproj de style SDK et du florissant écosystème NuGet.

Ce que nous devons faire

Conséquence de cette longue évolution, la plateforme Unity inclut une très grande base de code C++ qui interagit directement avec les objets .NET en utilisant des hypothèses spécifiques héritées du Mono .NET Runtime. Ceux-ci ne sont plus valides ou efficaces pour le .NET (Core) Runtime.

De plus, il existe un pipeline de compilation personnalisé compliqué lié à l'éditeur Unity qui ne repose pas sur MSBuild et ne peut donc pas facilement bénéficier de toutes les fonctionnalités standard.

Nous avons également discuté avec beaucoup d’entre vous au cours des dernières années, à la fois dans le cadre d’interviews et sur le forum Unity, pour voir ce que nous pourrions améliorer pour mieux permettre votre réussite. Ce que nous avons entendu, c’est que vous souhaitez utiliser le dernier langage C#, la technologie d’exécution .NET et le code C# tiers de NuGet. En ce qui concerne l'utilisation de la plateforme Unity, vous nous avez dit vouloir tirer le maximum du matériel cible avec des outils de test, de débogage et de profilage C# de haute qualité, et une bonne intégration entre l'API .NET standard et l'API Unity. En tant que programmeur C# Unity, vous voulez des outils Unity qui fonctionnent parfaitement avec le reste de votre boîte à outils et permettent une itération rapide afin que vous puissiez atteindre les meilleures performances d'exécution de sa catégorie.

Y arriver va nous prendre plusieurs années. Nous vous tiendrons au courant avec les mises à jour fréquentes du blog et du forum sur les défis techniques que nous rencontrons en cours de route.

Comment nous allons le faire

Notre première étape sur cette initiative a été de nous blottir avec toutes les personnes internes passionnées par C# et .NET dans Unity pour former un groupe C#/.NET Tech pour piloter cet effort.

Nous voulons nous appuyer sur l'écosystème .NET au lieu de développer des solutions personnalisées. Pour vous permettre de profiter des améliorations de performance et de productivité qui sont fournies avec les derniers SDK/Runtime .NET et MSBuild, nous souhaitons migrer du Mono .NET Runtime vers CoreCLR, le .NET (Core) Runtime moderne.

Cette initiative vous apporte également de l'innovation au-delà de l'univers .NET existant, avec pour objectifs de fournir des cycles d'itération .NET plus rapides sur vos scripts C#. Nous travaillerons à faire converger les solutions JIT et AOT (ahead-of-time) – IL2CPP et Burst – pour offrir le meilleur équilibre entre l’efficacité du temps de compilation et la qualité CodeGen.

En externe, nous travaillons avec des partenaires du secteur comme Microsoft et JetBrains pour nous assurer que les créateurs Unity utilisent la dernière technologie .NET. Nous accélérons également notre participation aux communautés open-source. Nous allons décomposer cette entreprise en plusieurs étapes. Voyons la suite.

Ce sur quoi nous travaillons en 2022

Cette année, les équipes prévoient de travailler sur les pistes suivantes.

Une infographie des piliers d'Unity Developer Experience
Workflow de développement C#

Le temps d'itération reste notre priorité absolue car nous savons que vous voulez tirer le meilleur parti de votre temps. Voici quelques exemples de ce que nous faisons pour améliorer cela.

  • Dans le cadre du pipeline de compilation, nous améliorons le temps passé par l’IL Post Processing qui est responsable de modifier les assemblys .NET compilés après la compilation de votre C#. Nous utilisons maintenant un processus persistant pour exécuter l'IL Post Processing après la phase de compilation, et cela peut nous faire perdre quelques centaines de millisecondes.
  • Le compilateur Burst étant utilisé plus fréquemment, nous améliorons la granularité de la détection des changements de code avec un algorithme de hachage transitif. Cela nous permet d'identifier quel code Burstable nous devons compiler plus rapidement. Nous travaillons sur le déplacement du compilateur Burst hors processus afin qu'il puisse compiler votre code plus rapidement grâce à son exécution dans un exécutable .NET 6.0 séparé.
  • Nous apportons également des améliorations au rechargement du domaine en améliorant les données de réflexion construites en coulisse chaque fois que le TypeCache est utilisé.
  • Nous allons ajouter des tests et une validation pour mieux suivre la régression du temps d’itération des paquets et des modèles de projet.

Pour la migration vers MSBuild, la première étape consiste à découpler notre pipeline de compilation de l'éditeur Unity et à le déplacer vers un processus séparé. C’est une opération compliquée car il y a des années de code hérité avec des milliers de lignes de code C++ et C# que nous devons démêler pour y parvenir – tout en restant rétrocompatible. Vous ne verrez pas de changements de votre point de vue, mais cela va ouvrir la voie à MSBuild et simplifier la maintenance.

Nous allons également améliorer l'expérience de débogage de l'IDE C# avec Burst en introduisant un mode qui fera automatiquement passer le débogueur en débogage géré lorsqu'un point d'arrêt est défini sur un chemin de code fonctionnant avec Burst. Cela signifie que vous n'aurez pas à supprimer manuellement l'attribut [BurstCompile] sur le chemin de code en cours de débogage.

Modernisation du runtime .NET

Le travail de migration vers .NET CoreCLR a déjà commencé, et c’est un voyage très difficile. Pour que nous puissions mener à bien cette migration, nous aimerions nous attaquer progressivement au problème et nous assurer que nous pouvons publier des morceaux de manière à maintenir la stabilité des projets Unity existants.

Nous prévoyons donc de réaliser cette migration en plusieurs phases :

  • Tout d’abord, nous fournirons le support de .NET CoreCLR pour les joueurs autonomes sur les plates-formes de bureau. Vous pourrez sélectionner cet environnement d'exécution dans les paramètres de votre lecteur en parallèle avec le backend Mono et IL2CPP existant. Cette première phase devrait nous aider à migrer la partie centrale de l'Unity Engine (qui est beaucoup plus petite que la partie Editeur), et permettra, espérons-le, de résoudre une bonne partie des défis techniques que comporte cette migration. Vous accéderez toujours au runtime .NET via l'API .NET Standard 2.1, et nous prévoyons de publier ce nouveau runtime en 2023.
  • Deuxièmement, nous allons porter l'Unity Editor sur .NET CoreCLR et supprimer le support du runtime .NET Mono en même temps. Cette deuxième phase va nous demander comment nous allons recharger vos scripts dans l'éditeur sans utiliser AppDomains et terminer le passage à .NET CoreCLR. Il s'agira également de mettre à niveau IL2CPP pour prendre en charge les bibliothèques de classes de base à partir du référentiel dotnet/runtime. Vous aurez enfin accès à l'API .NET 7.x ou 8.0 complète. Nous espérons sortir ce nouvel éditeur courant 2024.
Moderniser le runtime Unity

Le support .NET Standard 2.1 dans Unity 2021 LTS nous permet de commencer à moderniser l'environnement d'exécution Unity de plusieurs manières. Nous travaillons actuellement sur deux améliorations.

Amélioration du modèle de programmation async/await. Async/await est une approche de programmation fondamentale pour écrire du code de gameplay qui doit attendre qu'une opération asynchrone se termine sans bloquer la boucle principale du moteur.

En 2011, avant que async/await ne soit généralisé dans .NET, Unity introduisait des opérations asynchrones avec des coroutines basées sur des itérateurs, mais cette approche est incompatible avec async/await et peut être moins efficace. Entre-temps, .NET Standard 2.1 a amélioré le support d'async/await en C# et .NET avec l'introduction d'une gestion plus efficace des opérations d'async/await via ValueTask, et en autorisant votre propre système de type tâche via AsyncMethodBuilder.

Nous pouvons maintenant tirer parti de ces améliorations. Nous travaillons donc à activer l’utilisation de l’async/await avec les opérations asynchrones existantes dans Unity (comme attendre la trame suivante ou attendre une achèvement UnityWebRequest). Dans un premier temps, nous améliorons la prise en charge de l'annulation des tâches asynchrones en attente lorsqu'un MonoBehavior est détruit ou lorsque vous quittez le mode Lecture en utilisant des jetons d'annulation. Nous avons également travaillé en étroite collaboration avec nos plus grands contributeurs communautaires, tels que l'auteur d'UniTask, pour nous assurer qu'ils seront en mesure d'exploiter ces nouvelles fonctionnalités.

Réduction des allocations mémoire et des copies en exploitant Span. Comme Unity est un moteur C++ avec une couche C# Scripting, il y a beaucoup de données échangées entre les deux. Cela peut être inefficace car cela nécessite souvent soit de copier les données d'avant en arrière, soit d'allouer de nouveaux objets gérés.

Span a été introduit dans C# 7.2 pour améliorer de tels scénarios et est disponible par défaut dans .NET Standard 2.1. Ces dernières années, vous avez peut-être entendu ou lu de nombreuses améliorations significatives des performances apportées au .NET Runtime grâce à Span (voir les détails des améliorations dans .NET Core 2.1, .NET Core 3.0, .NET 6, .NET 6). Nous voulons tirer parti de son utilisation dans Unity puisque cela contribuera à réduire les allocations et, par conséquent, les pauses Garbage Collection tout en améliorant les performances globales de nombreuses API.

Rejoignez-nous sur ce voyage

Nous espérons que vous êtes tous aussi enthousiastes que nous à propos de ces changements et fonctionnalités.

Dites-nous ce que vous pensez de nos projets sur le forum. Nous allons également mettre à jour régulièrement la section ingénierie de la feuille de route Unity Platform, et vous pourrez nous faire part de vos demandes de fonctionnalités et suggestions de priorisation.

NDLR: La dernière mise à jour de cet article remonte à février 2023.