Отсутствуют интерфейсы API .NET в Unity и UWPMissing .NET APIs in Unity and UWP

При создании UWP-игры с использованием .NET вы, вероятно, обнаружите, что некоторые API-интерфейсы, которые вы использовали в редакторе Unity или в игре для ПК, не представлены для UWP.When building a UWP game using .NET, you may find that some APIs that you might use in the Unity editor or for a standalone PC game are not present for UWP. Это вызвано тем, что .NET для приложений UWP включает в себя набор типов, предоставленных в полной платформе .NET Framework для каждого пространства имен.That's because .NET for UWP apps includes a subset of the types provided in the full .NET Framework for each namespace.

Кроме того, некоторые игровые движки используют разные версии .NET, которые не полностью совместимы с .NET для UWP, например Mono в Unity.Additionally, some game engines use different flavors of .NET that aren't fully compatible with .NET for UWP, such as Unity's Mono. Поэтому при написании игры все может отлично работать в редакторе, но при выполнении сборки для UWP возможно получение таких ошибок: Тип или пространство имен Formatters не существует в пространстве имен System.Runtime.Serialization (отсутствует ссылка на сборку?)So when you're writing your game, everything might work fine in the editor, but when you go to build for UWP, you might get errors like this: The type or namespace 'Formatters' does not exist in the namespace 'System.Runtime.Serialization' (are you missing an assembly reference?)

К счастью, Unity предоставляет некоторые из этих отсутствующих API в виде методов расширения и заменяющих типов, которые описаны в разделе Универсальная платформа Windows: отсутствующие типы .NET на сервере сценариев .NET.Fortunately, Unity provides some of these missing APIs as extension methods and replacement types, which are described in Universal Windows Platform: Missing .NET Types on .NET Scripting Backend. Однако если вам нужная вам функциональная возможность, то в обзоре приложений .NET для Windows 8. x обсуждаются способы преобразования кода для использования WinRT или .net для Среда выполнения Windowsных API-интерфейсов.However, if the functionality you need is not here, .NET for Windows 8.x apps overview discusses ways you can convert your code to use WinRT or .NET for Windows Runtime APIs. (В нем рассматривается Windows 8, но это также относится к приложениям UWP для Windows 10.)(It discusses Windows 8, but is applicable to Windows 10 UWP apps as well.)

.NET Standard.NET Standard

Чтобы понять, почему некоторые API не работают, необходимо разобраться в разнообразии типов .NET и том, как UWP реализует .NET.To understand why some APIs might not be working, it's important to understand the different .NET flavors and how UWP implements .NET. .NET Standard — формальная спецификация для API-интерфейсов .NET, которая должна быть кросс-платформенной и унифицировать разновидности .NET.The .NET Standard is a formal specification of .NET APIs that is meant to be cross-platform, and unify the different .NET flavors. Каждая реализация .NET поддерживает определенную версию .NET Standard.Each implementation of .NET supports a certain version of the .NET Standard. Таблицу стандартов и реализаций можно увидеть в разделе Поддержка реализации .NET.You can see a table of standards and implementations at .NET implementation support.

Каждая версия UWP SDK соответствует своему уровню .NET Standard.Each version of the UWP SDK conforms to a different level of .NET Standard. Например, 16299 SDK (Fall Creators Update) поддерживает .NET Standard 2.0.For example, the 16299 SDK (the Fall Creators Update) supports .NET Standard 2.0.

Если вы хотите знать, поддерживаются ли определенные API-интерфейсы .NET в той версии UWP, на которую вы ориентируетесь, можно проверить Справочник по API .NET Standard и выбрать нужную версию .NET Standard, поддерживаемую данной версией UWP.If you want to know if a certain .NET API is supported in the UWP version that you're targeting, you can check the .NET Standard API Reference and select the version of the .NET Standard that's supported by that version of UWP.

Конфигурации сервера сценариевScripting backend configuration

Первое, что требуется сделать, если возникают проблемы при сборке для UWP — проверить параметры проигрывателя (Файл > Параметры сборкивыберите Универсальную платформу Windows, а затем Параметры проигрывателя).The first thing you should do if you're having trouble building for UWP is check the Player Settings (File > Build Settings, select Universal Windows Platform, and then Player Settings). В разделе Другие параметры > Конфигурации первые три раскрывающихся списка (Версия среды выполнения сценариев, Сервер сценариев и Уровень совместимости Api) содержат важные параметры, которые необходимо учитывать.Under Other Settings > Configuration, the first three dropdowns (Scripting Runtime Version, Scripting Backend, and Api Compatibility Level) are all important settings to consider.

Версия среды выполнения сценариев — то, что использует сервер сценариев Unity, что и это позволяет получить (примерно) равноценную поддержку версии .NET Framework, которую вы выбрали.The Scripting Runtime Version is what the Unity scripting backend uses which allows you to get the (roughly) equivalent version of .NET Framework support that you choose. Тем не менее, следует помнить, что будут поддерживаться не все API-интерфейсы в этой версию .NET Framework, а только те, которые представлены в версии .NET Standard, на которую ориентируется ваше приложение UWP.However, keep in mind that not all APIs in that version of the .NET Framework will be supported, only those in the version of .NET Standard that your UWP is targeting.

Часто с новыми выпусками .NET дополнительные API-интерфейсы добавляются в .NET Standard, что может позволить использовать один и тот же код для автономных приложений и UWP.Often with new .NET releases, more APIs are added to .NET Standard which might allow you to use the same code across standalone and UWP. Например, пространство имен System.Runtime.Serialization.Json впервые появилось в .NET Standard 2.0.For example, the System.Runtime.Serialization.Json namespace was introduced in .NET Standard 2.0. Если задать для Версии среды выполнения сценариев значение .NET 3.5 Equivalent (предназначено для более ранней версии .NET Standard), вы получите сообщение об ошибке при попытке использовать API-интерфейс; переведите переключатель в положение .NET 4.6 Equivalent (поддерживает .NET Standard 2.0), и API будет работать.If you set the Scripting Runtime Version to .NET 3.5 Equivalent (which targets an earlier version of the .NET Standard), you will get an error when trying to use the API; switch it to .NET 4.6 Equivalent (which supports .NET Standard 2.0), and the API will work.

Сервер сценариев может быть .NET или IL2CPP.The Scripting Backend can be .NET or IL2CPP. В этом разделе предполагается, что вы выбрали .NET, поскольку здесь возникают проблемы, рассматриваемые в этой статье.For this topic, we assume you have chosen .NET, since that's where the problems discussed here arise. Дополнительные сведения см. в разделе Серверы сценариев.See Scripting Backends for more information.

Наконец, следует задать Уровень совместимости Api согласно версии .NET, в которой необходимо запускать игру.Finally, you should set the Api Compatibility Level to the version of .NET that you want your game to run on. Это значение должно совпадать с Версией среды выполнения сценариев.This should match the Scripting Runtime Version.

Как правило, для Версии среды выполнения сценариев и Уровня совместимости Api следует выбирать последнюю доступную версию, чтобы обеспечить дополнительную совместимость с .NET Framework и таким образом использовать дополнительные API-интерфейсы .NET.In general, for Scripting Runtime Version and Api Compatibility Level, you should select the latest version available so as to have more compatibility with the .NET Framework, and thus allow you to use more .NET APIs.

Конфигурация: Версия среды выполнения сценариев; Сервер сценариев; Уровень совместимости API

Компиляция в зависимости от платформыPlatform-dependent compilation

Если вы разрабатываете игру на Unity для нескольких платформ, включая UWP, рекомендуется использовать компиляцию в зависимости от платформы, чтобы обеспечить выполнение предназначенного для UWP код только тогда, когда игра собрана как UWP.If you're building your Unity game for multiple platforms, including UWP, you'll want to use platform-dependent compilation to make sure that code intended for UWP is only run when the game is built as a UWP. Таким образом можно использовать полную платформу .NET для самостоятельного приложения для ПК и других платформ и API-интерфейсы WinRT для UWP, не получая ошибок построения.This way, you can use the full .NET Framework for standalone desktop and other platforms, and WinRT APIs for UWP, without getting build errors.

Используйте следующие директивы только для компиляции кода при запуске в качестве приложения UWP:Use the following directives to only compile code when running as a UWP app:

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

Примечание

NETFX_CORE предназначен только для проверки того, компилируется ли код C# в серверной части сценариев .NET.NETFX_CORE is only meant to check if you're compiling C# code against the .NET scripting backend. Если вы используете другую серверную часть сценариев, например IL2CPP, используйте ENABLE_WINMD_SUPPORT вместо нее.If you're using a different scripting backend, such as IL2CPP, use ENABLE_WINMD_SUPPORT instead.

Полный список директив компиляции в зависимости от платформы см. в разделе Компиляция в зависимости от платформы.For the full list of platform-dependent compilation directives, see Platform dependent compilation.

Распространенные проблемы и обходные решения для нихCommon issues and workarounds

Ниже описаны распространенные проблемы, которые могут возникнуть в случаях, где API-интерфейсы .NET отсутствуют в наборе UWP, и способы их устранения.The following scenarios describe common issues that might arise where .NET APIs are missing from the UWP subset, and ways to get around them.

Сериализация данных с помощью BinaryFormatterData serialization using BinaryFormatter

В играх часто производится сериализация для сохранения данных, чтобы игроки не могли ими манипулировать.It is common for games to serialize save data so that players can't easily manipulate it. Тем не менее, средство BinaryFormatter, которое сериализует объект в двоичный файл, не доступно в предыдущих версиях .NET Standard (до 2.0).However, BinaryFormatter, which serializes an object into binary, is not available in earlier versions of the .NET Standard (prior to 2.0). Рассмотрите возможность использования XmlSerializer или DataContractJsonSerializer вместо него.Consider using XmlSerializer or DataContractJsonSerializer instead.

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();
}

Операции ввода-выводаI/O operations

Некоторые типы в пространстве имен System.IO, такие как FileStream, не доступны в предыдущих версиях .NET Standard.Some types in the System.IO namespace, such as FileStream, are not available in earlier versions of the .NET Standard. Однако Unity предоставляет типы Directory, File и FileStream, чтобы их можно было использовать в игре.However, Unity does provide the Directory, File, and FileStream types so you can use them in your game.

Кроме того, можно использовать API-интерфейсы Windows.Storage, которые доступны только для приложений UWP.Alternatively, you can use the Windows.Storage APIs, which are only available to UWP apps. Тем не менее, эти API-интерфейсы позволяют приложению выполнять запись только выделенную ему область и не предоставляют неограниченный доступ к файловой системе.However, these APIs restrict the app to writing to their specific storage, and do not give it free access to the entire file system. Дополнительные сведения см. в разделе Файлы, папки и библиотеки.See Files, folders, and libraries for more information.

Важное замечание: метод Close доступен только в .NET Standard 2.0 и более поздних версиях (хотя Unity предоставляет метод расширения).One important note is that the Close method is only available in .NET Standard 2.0 and later (though Unity provides an extension method). Вместо него предлагается использовать Dispose.Use Dispose instead.

ПотокиThreading

Некоторые типы в пространстве имен System.Threading, такие как ThreadPool, не доступны в предыдущих версиях .NET Standard.Some types in the System.Threading namespaces, such as ThreadPool, are not available in earlier versions of the .NET Standard. В таких случаях можно использовать вместо него пространство имен Windows.System.Threading.In these cases, you can use the Windows.System.Threading namespace instead.

Вот как можно обрабатывать потоки в игре Unity, используя компиляцию в зависимости от платформы для подготовки для платформ UWP и не-UWP:Here's how you could handle threading in a Unity game, using platform-dependent compilation to prepare for both UWP and non-UWP platforms:

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

БезопасностьSecurity

Некоторые их пространств имен **System.Security.***, например System.Security.Cryptography.X509Certificates, недоступны при разработке игр Unity для UWP.Some of the System.Security.* namespaces, such as System.Security.Cryptography.X509Certificates, are not available when you build a Unity game for UWP. В таких случаях используйте API-интерфейсы **Windows.Security.***, которые охватывают почти всю ту же функциональность.In these cases, use the Windows.Security.* APIs, which cover much of the same functionality.

Следующий пример просто получает сертификаты из хранилища сертификатов с заданным именем:The following example simply gets the certificates from a certificate store with the given name:

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
    }

Подробнее об использовании API-интерфейсов WinRT см. в статье Безопасность.See Security for more information about using the WinRT security APIs.

СетьNetworking

Некоторые их пространств имен **System.Net.***, например System.Net.Mail, также недоступны при разработке игр Unity для UWP.Some of the System.Net.* namespaces, such as System.Net.Mail, are also not available when building a Unity game for UWP. Для большинства из этих API используйте соответствующие API WinRT Windows.Networking.* и **Windows.Web.***, которые реализуют схожую функциональность.For most of these APIs, use the corresponding Windows.Networking.* and Windows.Web.* WinRT APIs to get similar functionality. Подробнее: Сеть и веб-службы.See Networking and web services for more information.

В случае System.Net.Mail используйте пространство имен Windows.ApplicationModel.Email.In the case of System.Net.Mail, use the Windows.ApplicationModel.Email namespace. Подробнее: Отправка сообщения электронной почты.See Send email for more information.

См. также разделSee also