API .NET manquantes dans Unity et UWP
Lorsque vous créez un jeu UWP à l’aide de .NET, vous pouvez constater que certaines API que vous pouvez utiliser dans l’éditeur Unity ou pour un jeu PC autonome ne sont pas présentes pour UWP. Cela est dû au fait que .NET pour les applications UWP inclut un sous-ensemble des types fournis dans le .NET Framework complet pour chaque espace de noms.
En outre, certains moteurs de jeu utilisent différentes versions de .NET qui ne sont pas entièrement compatibles avec .NET pour UWP, telles que Mono d’Unity. Ainsi, lorsque vous écrivez votre jeu, tout peut fonctionner correctement dans l’éditeur, mais lorsque vous accédez à la génération pour UWP, vous pouvez obtenir des erreurs comme suit : Le type ou l’espace de noms « Formatters » n’existe pas dans l’espace de noms « System.Runtime.Serialization » (manquez-vous une référence d’assembly ?)
Heureusement, Unity fournit certaines de ces API manquantes en tant que méthodes d’extension et types de remplacement, qui sont décrits dans plateforme Windows universelle : Types .NET manquants sur le serveur principal de script .NET. Toutefois, si la fonctionnalité dont vous avez besoin n’est pas ici, .NET pour les applications Windows 8.x décrit les façons dont vous pouvez convertir votre code pour utiliser WinRT ou .NET pour les API Windows Runtime. (Il traite également de Windows 8, mais s’applique également aux applications UWP Windows 10.)
.NET Standard
Pour comprendre pourquoi certaines API peuvent ne pas fonctionner, il est important de comprendre les différentes versions de .NET et la façon dont UWP implémente .NET. . NET Standard est une spécification formelle des API .NET destinées à être multiplateformes et à unifier les différentes versions de .NET. Chaque implémentation de .NET prend en charge une certaine version de .NET Standard. Vous pouvez voir une table des normes et des implémentations au niveau de la prise en charge de l’implémentation .NET.
Chaque version du Kit de développement logiciel (SDK) UWP est conforme à un niveau différent de .NET Standard. Par exemple, le SDK 16299 (Fall Creators Update) prend en charge .NET Standard 2.0.
Si vous souhaitez savoir si une certaine API .NET est prise en charge dans la version UWP que vous ciblez, vous pouvez vérifier la référence de l’API .NET Standard et sélectionner la version de .NET Standard prise en charge par cette version de UWP.
Configuration du serveur principal de script
La première chose que vous devez faire si vous rencontrez des problèmes de génération pour UWP est de vérifier les paramètres du lecteur (Paramètres de build de fichier>, sélectionnez plateforme Windows universelle, puis paramètres du lecteur). Sous Autres paramètres > de configuration, les trois premières listes déroulantes (version du runtime de script, back-end de script et niveau de compatibilité d’API) sont tous les paramètres importants à prendre en compte.
La version du runtime de script est ce que le back-end de script Unity utilise, ce qui vous permet d’obtenir la version équivalente (à peu près) de .NET Framework prise en charge que vous choisissez. Toutefois, gardez à l’esprit que toutes les API de cette version du .NET Framework ne seront pas prises en charge, seules celles de la version de .NET Standard que votre UWP cible.
Souvent avec de nouvelles versions de .NET, d’autres API sont ajoutées à .NET Standard, ce qui peut vous permettre d’utiliser le même code sur une version autonome et UWP. Par exemple, l’espace de noms System.Runtime.Serialization.Json a été introduit dans .NET Standard 2.0. Si vous définissez la version du runtime de script sur .NET 3.5 Équivalent (qui cible une version antérieure du .NET Standard), vous obtiendrez une erreur lors de la tentative d’utilisation de l’API ; basculez-la vers .NET 4.6 Équivalent (qui prend en charge .NET Standard 2.0) et l’API fonctionnera.
Le serveur principal de script peut être .NET ou IL2CPP. Pour cette rubrique, nous partons du principe que vous avez choisi .NET, car c’est là que les problèmes abordés ici se produisent. Pour plus d’informations, consultez Scripting Backends .
Enfin, vous devez définir le niveau de compatibilité d’API sur la version de .NET sur laquelle vous souhaitez que votre jeu s’exécute. Cela doit correspondre à la version du runtime de script.
En général, pour la version du runtime de script et le niveau de compatibilité d’API, vous devez sélectionner la dernière version disponible afin d’avoir plus de compatibilité avec .NET Framework, et ainsi vous permettre d’utiliser davantage d’API .NET.
Compilation dépendante de la plateforme
Si vous créez votre jeu Unity pour plusieurs plateformes, y compris UWP, vous devez utiliser la compilation dépendante de la plateforme pour vous assurer que le code destiné à UWP est exécuté uniquement lorsque le jeu est généré en tant qu’UWP. De cette façon, vous pouvez utiliser le .NET Framework complet pour les ordinateurs de bureau autonomes et d’autres plateformes, ainsi que les API WinRT pour UWP, sans obtenir d’erreurs de génération.
Utilisez les directives suivantes pour compiler uniquement du code lors de l’exécution en tant qu’application UWP :
#if NETFX_CORE
// Your UWP code here
#else
// Your standard code here
#endif
Remarque
NETFX_CORE
est destiné uniquement à vérifier si vous compilez du code C# sur le back-end de script .NET. Si vous utilisez un autre serveur principal de script, tel qu’IL2CPP, utilisez plutôt ENABLE_WINMD_SUPPORT .
Problèmes courants et solutions de contournement
Les scénarios suivants décrivent les problèmes courants qui peuvent survenir lorsque les API .NET sont manquantes dans le sous-ensemble UWP et comment les contourner.
Sérialisation des données à l’aide de BinaryFormatter
Il est courant que les jeux sérialisent les données d’enregistrement afin que les joueurs ne puissent pas facilement les manipuler. Toutefois, BinaryFormatter, qui sérialise un objet en binaire, n’est pas disponible dans les versions antérieures de .NET Standard (antérieures à la version 2.0). Envisagez plutôt d’utiliser XmlSerializer ou DataContractJsonSerializer .
private void Save()
{
SaveData data = new SaveData(); // User-defined object to serialize
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(typeof(SaveData));
FileStream stream =
new FileStream(Application.persistentDataPath, FileMode.CreateNew);
serializer.WriteObject(stream, data);
stream.Dispose();
}
Opérations d’E/S
Certains types de l’espace de noms System.IO , tels que FileStream, ne sont pas disponibles dans les versions antérieures de .NET Standard. Toutefois, Unity fournit les types Répertoire, Fichier et FileStream pour pouvoir les utiliser dans votre jeu.
Vous pouvez également utiliser les API Windows.Storage , qui sont uniquement disponibles pour les applications UWP. Toutefois, ces API limitent l’écriture de l’application à leur stockage spécifique et ne lui donnent pas un accès gratuit à l’ensemble du système de fichiers. Pour plus d’informations, consultez Fichiers, dossiers et bibliothèques .
Une remarque importante est que la méthode Close n’est disponible que dans .NET Standard 2.0 et versions ultérieures (bien que Unity fournit une méthode d’extension). Utilisez Dispose à la place.
Thread
Certains types dans les espaces de noms System.Threading , tels que ThreadPool, ne sont pas disponibles dans les versions antérieures de .NET Standard. Dans ces cas, vous pouvez utiliser l’espace de noms Windows.System.Threading à la place.
Voici comment gérer le threading dans un jeu Unity, à l’aide de la compilation dépendante de la plateforme pour préparer les plateformes UWP et non UWP :
private void UsingThreads()
{
#if NETFX_CORE
Windows.System.Threading.ThreadPool.RunAsync(workItem => SomeMethod());
#else
System.Threading.ThreadPool.QueueUserWorkItem(workItem => SomeMethod());
#endif
}
Sécurité
Certaines de System.Security.* les espaces de noms, tels que System.Security.Cryptography.X509Certificates, ne sont pas disponibles lorsque vous créez un jeu Unity pour UWP. Dans ces cas, utilisez Windows.Security.* API, qui couvrent une grande partie des mêmes fonctionnalités.
L’exemple suivant obtient simplement les certificats d’un magasin de certificats avec le nom donné :
private async void GetCertificatesAsync(string certStoreName)
{
#if NETFX_CORE
IReadOnlyList<Certificate> certs = await CertificateStores.FindAllAsync();
IEnumerable<Certificate> myCerts =
certs.Where((certificate) => certificate.StoreName == certStoreName);
#else
X509Store store = new X509Store(certStoreName, StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly);
X509Certificate2Collection certs = store.Certificates;
#endif
}
Pour plus d’informations sur l’utilisation des API de sécurité WinRT, consultez Sécurité .
Mise en réseau
Certains des System.Net.* les espaces de noms, tels que System.Net.Mail, ne sont pas disponibles lors de la création d’un jeu Unity pour UWP. Pour la plupart de ces API, utilisez Windows.Networking correspondant .* et Windows.Web.* API WinRT pour obtenir des fonctionnalités similaires. Pour plus d’informations, consultez Mise en réseau et services web.
Dans le cas de System.Net.Mail, utilisez l’espace de noms Windows.ApplicationModel.Email . Pour plus d’informations, consultez Envoyer un e-mail .