Freigeben über


Fehlende .NET-APIs in Unity und UWP

Beim Erstellen eines UWP-Spiels mit .NET stellen Sie möglicherweise fest, dass einige APIs, die Sie möglicherweise im Unity-Editor oder für ein eigenständiges PC-Spiel verwenden, für UWP nicht vorhanden sind. Das liegt daran, dass .NET für UWP-Apps eine Teilmenge der Typen enthält, die im vollständigen .NET Framework für jeden Namespace bereitgestellt werden.

Darüber hinaus verwenden einige Spielengines unterschiedliche Varianten von .NET, die nicht vollständig mit .NET für UWP kompatibel sind, z. B. Unitys Mono. Wenn Sie also Ihr Spiel schreiben, funktioniert möglicherweise alles im Editor einwandfrei, aber wenn Sie zum Erstellen für UWP wechseln, erhalten Sie möglicherweise Folgende Fehler: Der Typ oder Namespace "Formatters" ist im Namespace "System.Runtime.Serialization" nicht vorhanden (fehlen Sie einen Assemblyverweis?)

Glücklicherweise stellt Unity einige dieser fehlenden APIs als Erweiterungsmethoden und Ersetzungstypen bereit, die in Universal Windows Platform: Fehlende .NET-Typen im .NET Scripting Backendbeschrieben werden. Wenn die benötigte Funktionalität jedoch nicht vorhanden ist, wird im Überblick über .NET für Windows 8.x-Apps erläutert, wie Sie Ihren Code konvertieren können, um WinRT oder die .NET-APIs für Windows-Runtime zu verwenden. (Es wird Windows 8 erläutert, gilt aber auch für Windows 10 UWP-Apps.)

.NET Standard

Um zu verstehen, warum einige APIs möglicherweise nicht funktionieren, ist es wichtig, die verschiedenen .NET-Versionen zu kennen und wie UWP .NET implementiert. Der .NET Standard ist eine formale Spezifikation von .NET-APIs, die plattformübergreifend sein sollen, und die verschiedenen .NET-Varianten zu vereinheitlichen. Jede Implementierung von .NET unterstützt eine bestimmte Version von .NET Standard. Eine Tabelle mit Standards und Implementierungen finden Sie unter .NET-Implementierungsunterstützung.

Jede Version des UWP SDK entspricht einer anderen Ebene von .NET Standard. Beispielsweise unterstützt das 16299 SDK (Fall Creators Update) .NET Standard 2.0.

Wenn Sie wissen möchten, ob eine bestimmte .NET-API in der UWP-Version unterstützt wird, auf die Sie abzielen, können Sie die .NET Standard-API-Referenz überprüfen und die Version von .NET Standard auswählen, die von dieser Version von UWP unterstützt wird.

Skripting-Back-End-Konfiguration

Das Erste, was Sie tun sollten, wenn Sie Probleme beim Erstellen von UWP haben, ist die Player Settings (Datei > Buildeinstellungen, wählen Sie Universal Windows Platformaus, und Player Settings). Unter > Configurationsind die ersten drei Dropdowns (Scripting Runtime Version, Scripting Backendund API Compatibility Level) entscheidend zu berücksichtigen.

Die Scripting Runtime-Version verwendet das Unity-Skripting-Back-End, mit dem Sie die von Ihnen ausgewählte (ungefähr) entsprechende Version von .NET Framework-Unterstützung abrufen können. Beachten Sie jedoch, dass nicht alle APIs in dieser Version von .NET Framework unterstützt werden, nur diejenigen in der Version von .NET Standard, auf die Ihre UWP ausgerichtet ist.

Häufig werden mit neuen .NET-Versionen weitere APIs zu .NET Standard hinzugefügt, wodurch Sie denselben Code sowohl für eigenständige Anwendungen als auch für die Universelle Windows-Plattform (UWP) verwenden können. Beispielsweise wurde der System.Runtime.Serialization.Json Namespace in .NET Standard 2.0 eingeführt. Wenn Sie die Skripting-Runtime-Version auf .NET 3.5 Equivalent festlegen (die auf eine frühere Version von .NET Standard ausgerichtet ist), wird beim Versuch, die API zu verwenden, eine Fehlermeldung angezeigt. wechseln Sie zu .NET 4.6 Equivalent (unterstützt .NET Standard 2.0), und die API funktioniert.

Das Scripting Backend kann .NET oder IL2CPPsein. Für dieses Thema wird davon ausgegangen, dass Sie .NET-ausgewählt haben, da hier die hier erläuterten Probleme auftreten. Weitere Informationen finden Sie unter Scripting-Backends.

Schließlich sollten Sie die API-Kompatibilitätsstufe auf die Version von .NET festlegen, auf der Ihr Spiel ausgeführt werden soll. Dies sollte mit der Scripting Runtime-Versionübereinstimmen.

Im Allgemeinen sollten Sie für die Skripting-Runtime-Version und api-Kompatibilitätsstufe die neueste verfügbare Version auswählen, damit Sie mehr Kompatibilität mit .NET Framework haben und somit mehr .NET-APIs verwenden können.

Konfiguration: Skripting-Runtime-Version; Skripting Backend; API-Kompatibilitätsstufe

Plattformabhängige Kompilierung

Wenn Sie Ihr Unity-Spiel für mehrere Plattformen erstellen, einschließlich UWP, sollten Sie die plattformabhängige Kompilierung verwenden, um sicherzustellen, dass der für UWP vorgesehene Code nur ausgeführt wird, wenn das Spiel als UWP erstellt wird. Auf diese Weise können Sie das vollständige .NET Framework für eigenständige Desktop- und andere Plattformanwendungen sowie die WinRT-APIs für UWP verwenden, ohne dass es zu Buildfehlern kommt.

Verwenden Sie die folgenden Direktiven, um Code nur zu kompilieren, wenn sie als UWP-App ausgeführt werden:

#if NETFX_CORE
    // Your UWP code here
#else
    // Your standard code here
#endif

Hinweis

NETFX_CORE ist nur gedacht, um zu überprüfen, ob Sie C#-Code für das .NET-Skripting-Back-End kompilieren. Wenn Sie ein anderes Skript-Backend wie IL2CPP verwenden, verwenden Sie stattdessen ENABLE_WINMD_SUPPORT.

Häufig auftretende Probleme und Problemumgehungen

In den folgenden Szenarien werden häufige Probleme beschrieben, die auftreten können, wenn .NET-APIs aus der UWP-Teilmenge fehlen, und Möglichkeiten, um sie zu umgehen.

Daten serialisierung mit BinaryFormatter

Es ist üblich, dass Spiele Daten serialisieren, damit Spieler sie nicht einfach bearbeiten können. BinaryFormatter-, der ein Objekt in eine Binärdatei serialisiert, ist jedoch in früheren Versionen von .NET Standard (vor 2.0) nicht verfügbar. In Betracht ziehen Sie stattdessen die Verwendung von XmlSerializer oder 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();
}

E/A-Vorgänge

Einige Typen im System.IO-Namespace , z. B. FileStream, sind in früheren Versionen von .NET Standard nicht verfügbar. Unity stellt jedoch die Typen "Directory", "File" und "FileStream" bereit, damit Sie sie in Ihrem Spiel verwenden können.

Alternativ können Sie die Windows.Storage-APIs verwenden, die nur für UWP-Apps verfügbar sind. Diese APIs beschränken die App jedoch auf das Schreiben in ihren spezifischen Speicher und gewähren ihm keinen kostenlosen Zugriff auf das gesamte Dateisystem. Weitere Informationen finden Sie unter Dateien, Ordner und Bibliotheken.

Ein wichtiger Hinweis ist, dass die Close-Methode nur in .NET Standard 2.0 und höher verfügbar ist (obwohl Unity eine Erweiterungsmethode bereitstellt). Verwenden Sie stattdessen Dispose.

Einfädelnd

Einige Typen in den System.Threading Namespaces, wie z. B. ThreadPool-, sind in früheren Versionen des .NET-Standards nicht verfügbar. In diesen Fällen können Sie stattdessen den Windows.System.Threading Namespace verwenden.

Hier erfahren Sie, wie Sie Threading in einem Unity-Spiel mit plattformabhängiger Kompilierung einsetzen können, um sich sowohl auf UWP- als auch auf Nicht-UWP-Plattformen vorzubereiten:

private void UsingThreads()
{
#if NETFX_CORE
    Windows.System.Threading.ThreadPool.RunAsync(workItem => SomeMethod());
#else
    System.Threading.ThreadPool.QueueUserWorkItem(workItem => SomeMethod());
#endif
}

Sicherheit

Einige der System.Security.* Namespaces, z. B. System.Security.Cryptography.X509Certificates, sind nicht verfügbar, wenn Sie ein Unity-Spiel für UWP erstellen. Verwenden Sie in diesen Fällen windows.Security.* APIs, die einen Großteil der gleichen Funktionalität abdecken.

Im folgenden Beispiel werden einfach die Zertifikate aus einem Zertifikatspeicher mit dem angegebenen Namen abgerufen:

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
    }

Weitere Informationen zur Verwendung der WinRT-Sicherheits-APIs finden Sie unter "Sicherheit ".

Vernetzung

Einige der System.Net.* Namespaces, z. B. System.Net.Mail, sind auch beim Erstellen eines Unity-Spiels für UWP nicht verfügbar. Verwenden Sie für die meisten dieser APIs die entsprechenden Windows.Networking.* und Windows.Web.* WinRT-APIs, um ähnliche Funktionen zu erhalten. Weitere Informationen finden Sie unter Networking und Webdienste .

Verwenden Sie für System.Net.Mail-den Windows.ApplicationModel.Email namespace. Weitere Informationen finden Sie unter E-Mail senden.

Siehe auch