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

При создании UWP-игры с использованием .NET вы, вероятно, обнаружите, что некоторые API-интерфейсы, которые вы использовали в редакторе Unity или в игре для ПК, не представлены для UWP. Это вызвано тем, что .NET для приложений UWP включает в себя набор типов, предоставленных в полной платформе .NET Framework для каждого пространства имен.

Кроме того, некоторые игровые движки используют разные версии .NET, которые не полностью совместимы с .NET для UWP, например Mono в Unity. Поэтому при написании игры все может отлично работать в редакторе, но при выполнении сборки для UWP возможно получение таких ошибок: Тип или пространство имен Formatters не существует в пространстве имен System.Runtime.Serialization (отсутствует ссылка на сборку?)

К счастью, Unity предоставляет некоторые из этих отсутствующих API в виде методов расширения и заменяющих типов, которые описаны в разделе Универсальная платформа Windows: отсутствующие типы .NET на сервере сценариев .NET. Однако если необходимые функции отсутствуют, в обзоре .NET для приложений Windows 8.x рассматриваются способы преобразования кода для использования WinRT или .NET для среда выполнения Windows API. (В нем рассматривается Windows 8, но это также относится к приложениям UWP для Windows 10.)

.NET Standard

Чтобы понять, почему некоторые API не работают, необходимо разобраться в разнообразии типов .NET и том, как UWP реализует .NET. .NET Standard — формальная спецификация для API-интерфейсов .NET, которая должна быть кросс-платформенной и унифицировать разновидности .NET. Каждая реализация .NET поддерживает определенную версию .NET Standard. Таблицу стандартов и реализаций можно увидеть в разделе Поддержка реализации .NET.

Каждая версия UWP SDK соответствует своему уровню .NET Standard. Например, 16299 SDK (Fall Creators Update) поддерживает .NET Standard 2.0.

Если вы хотите знать, поддерживаются ли определенные API-интерфейсы .NET в той версии UWP, на которую вы ориентируетесь, можно проверить Справочник по API .NET Standard и выбрать нужную версию .NET Standard, поддерживаемую данной версией UWP.

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

Если у вас возникли проблемы со сборкой для UWP, сначала проверьте параметры проигрывателя (параметры сборки файлов>, выберите универсальная платформа Windows, а затем — Параметры проигрывателя). В разделе Конфигурация других параметров первые три раскрывающихся списка (версия среды выполнения сценариев, серверная часть скриптов> и уровень совместимости API) — это важные параметры, которые следует учитывать.

Версия среды выполнения сценариев — то, что использует сервер сценариев Unity, что и это позволяет получить (примерно) равноценную поддержку версии .NET Framework, которую вы выбрали. Тем не менее, следует помнить, что будут поддерживаться не все API-интерфейсы в этой версию .NET Framework, а только те, которые представлены в версии .NET Standard, на которую ориентируется ваше приложение UWP.

Часто с новыми выпусками .NET дополнительные API-интерфейсы добавляются в .NET Standard, что может позволить использовать один и тот же код для автономных приложений и UWP. Например, пространство имен System.Runtime.Serialization.Json впервые появилось в .NET Standard 2.0. Если задать для Версии среды выполнения сценариев значение .NET 3.5 Equivalent (предназначено для более ранней версии .NET Standard), вы получите сообщение об ошибке при попытке использовать API-интерфейс; переведите переключатель в положение .NET 4.6 Equivalent (поддерживает .NET Standard 2.0), и API будет работать.

Сервер сценариев может быть .NET или IL2CPP. В этом разделе предполагается, что вы выбрали .NET, поскольку здесь возникают проблемы, рассматриваемые в этой статье. Дополнительные сведения см. в разделе Серверы сценариев.

Наконец, следует задать Уровень совместимости Api согласно версии .NET, в которой необходимо запускать игру. Это значение должно совпадать с Версией среды выполнения сценариев.

Как правило, для Версии среды выполнения сценариев и Уровня совместимости Api следует выбирать последнюю доступную версию, чтобы обеспечить дополнительную совместимость с .NET Framework и таким образом использовать дополнительные API-интерфейсы .NET.

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

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

Если вы разрабатываете игру на Unity для нескольких платформ, включая UWP, рекомендуется использовать компиляцию в зависимости от платформы, чтобы обеспечить выполнение предназначенного для UWP код только тогда, когда игра собрана как UWP. Таким образом можно использовать полную платформу .NET для самостоятельного приложения для ПК и других платформ и API-интерфейсы WinRT для UWP, не получая ошибок построения.

Используйте следующие директивы только для компиляции кода при запуске в качестве приложения UWP:

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

Примечание

NETFX_CORE предназначен только для проверки того, компилируется ли код C# в серверной части скриптов .NET. Если вы используете другую серверную часть сценариев, например IL2CPP, используйте ENABLE_WINMD_SUPPORT .

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

Ниже описаны распространенные проблемы, которые могут возникнуть в случаях, где API-интерфейсы .NET отсутствуют в наборе UWP, и способы их устранения.

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

В играх часто производится сериализация для сохранения данных, чтобы игроки не могли ими манипулировать. Тем не менее, средство BinaryFormatter, которое сериализует объект в двоичный файл, не доступно в предыдущих версиях .NET Standard (до 2.0). Рассмотрите возможность использования XmlSerializer или 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();
}

Операции ввода-вывода

Некоторые типы в пространстве имен System.IO, такие как FileStream, не доступны в предыдущих версиях .NET Standard. Однако Unity предоставляет типы Directory, File и FileStream, чтобы их можно было использовать в игре.

Кроме того, можно использовать API-интерфейсы Windows.Storage, которые доступны только для приложений UWP. Тем не менее, эти API-интерфейсы позволяют приложению выполнять запись только выделенную ему область и не предоставляют неограниченный доступ к файловой системе. Дополнительные сведения см. в разделе Файлы, папки и библиотеки.

Важное замечание: метод Close доступен только в .NET Standard 2.0 и более поздних версиях (хотя Unity предоставляет метод расширения). Вместо него предлагается использовать Dispose.

Потоки

Некоторые типы в пространстве имен System.Threading, такие как ThreadPool, не доступны в предыдущих версиях .NET Standard. В таких случаях можно использовать вместо него пространство имен Windows.System.Threading.

Вот как можно обрабатывать потоки в игре Unity, используя компиляцию в зависимости от платформы для подготовки для платформ UWP и не-UWP:

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

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

Некоторые их пространств имен System.Security.*, например System.Security.Cryptography.X509Certificates, недоступны при разработке игр Unity для UWP. В таких случаях используйте API-интерфейсы Windows.Security.*, которые охватывают почти всю ту же функциональность.

Следующий пример просто получает сертификаты из хранилища сертификатов с заданным именем:

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 см. в статье Безопасность.

Сеть

Некоторые из System.Net. * пространства имен, такие как System.Net.Mail, также недоступны при создании игры Unity для UWP. Для большинства из этих API используйте соответствующие API WinRT Windows.Networking.* и Windows.Web.*, которые реализуют схожую функциональность. Подробнее: Сеть и веб-службы.

В случае System.Net.Mail используйте пространство имен Windows.ApplicationModel.Email. Подробнее: Отправка сообщения электронной почты.

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