APIs do .NET ausentes no Unity e na UWP

Ao criar um jogo UWP usando o .NET, você pode descobrir que algumas APIs que você pode usar no editor do Unity ou para um jogo de computador autônomo não estão presentes para UWP. Isso ocorre porque o .NET para aplicativos UWP inclui um subconjunto dos tipos fornecidos no .NET Framework completo para cada namespace.

Além disso, alguns mecanismos de jogo usam diferentes tipos de .NET que não são totalmente compatíveis com o .NET para UWP, como o Mono do Unity. Portanto, quando você estiver escrevendo seu jogo, tudo pode funcionar bem no editor, mas quando você for compilar para UWP, poderá obter erros como este: O tipo ou namespace 'Formatters' não existe no namespace 'System.Runtime.Serialization' (você está perdendo uma referência de assembly?)

Felizmente, o Unity fornece algumas dessas APIs ausentes como métodos de extensão e tipos de substituição, que são descritos em Plataforma Universal do Windows: Tipos .NET ausentes no back-end de script do .NET. No entanto, se a funcionalidade de que você precisa não estiver aqui, a visão geral dos aplicativos do .NET para Windows 8.x discute maneiras de converter seu código para usar APIs do WinRT ou do .NET para Windows Runtime. (Ele discute o Windows 8, mas também é aplicável a aplicativos UWP do Windows 10.)

.NET Standard

Para entender por que algumas APIs podem não estar funcionando, é importante entender os diferentes tipos de .NET e como a UWP implementa o .NET. O .NET Standard é uma especificação formal de APIs do .NET que deve ser multiplataforma e unificar os diferentes tipos do .NET. Cada implementação do .NET dá suporte a uma determinada versão do .NET Standard. Você pode ver uma tabela de padrões e implementações em Suporte à implementação do .NET.

Cada versão do SDK da UWP está em conformidade com um nível diferente do .NET Standard. Por exemplo, o SDK 16299 (o Fall Creators Update) dá suporte ao .NET Standard 2.0.

Se você quiser saber se há suporte para uma determinada API do .NET na versão UWP que você está direcionando, verifique a Referência da API do .NET Standard e selecione a versão do .NET Standard compatível com essa versão da UWP.

Configuração de back-end de script

A primeira coisa que você deve fazer se estiver tendo problemas para criar para UWP é verificar as Configurações do Player (Configurações de Build de Arquivo>, selecione Plataforma Universal do Windows e, em seguida, Configurações do Player). Em Configuração de Outras Configurações>, as três primeiras listas suspensas (Versão do Tempo de Execução de Script, Back-end de Script e Nível de Compatibilidade da API) são configurações importantes a serem consideradas.

A Versão do Tempo de Execução de Script é o que o back-end de script do Unity usa, o que permite que você obtenha a versão (aproximadamente) equivalente do suporte ao .NET Framework que você escolher. No entanto, lembre-se de que nem todas as APIs nessa versão do .NET Framework terão suporte, apenas aquelas na versão do .NET Standard que sua UWP está direcionando.

Muitas vezes, com novas versões do .NET, mais APIs são adicionadas ao .NET Standard, o que pode permitir que você use o mesmo código em autônomo e UWP. Por exemplo, o namespace System.Runtime.Serialization.Json foi introduzido no .NET Standard 2.0. Se você definir a Versão do Tempo de Execução de Script como Equivalente ao .NET 3.5 (que se destina a uma versão anterior do .NET Standard), receberá um erro ao tentar usar a API; alterne-a para o .NET 4.6 Equivalente (que dá suporte ao .NET Standard 2.0) e a API funcionará.

O back-end de script pode ser .NET ou IL2CPP. Para este tópico, presumimos que você tenha escolhido .NET, pois é aí que surgem os problemas discutidos aqui. Consulte Backends de script para obter mais informações.

Por fim, você deve definir o Nível de Compatibilidade da API para a versão do .NET na qual deseja que seu jogo seja executado. Isso deve corresponder à versão do Scripting Runtime.

Em geral, para a Versão do Tempo de Execução de Script e o Nível de Compatibilidade da API, você deve selecionar a versão mais recente disponível para ter mais compatibilidade com o .NET Framework e, assim, permitir que você use mais APIs do .NET.

Configuração: Versão do tempo de execução do script; Backend de scripts; Nível de compatibilidade da API

Compilação dependente da plataforma

Se você estiver criando seu jogo Unity para várias plataformas, incluindo UWP, convém usar a compilação dependente da plataforma para garantir que o código destinado à UWP seja executado apenas quando o jogo for criado como uma UWP. Dessa forma, você pode usar o .NET Framework completo para área de trabalho autônoma e outras plataformas e APIs do WinRT para UWP, sem obter erros de build.

Use as seguintes diretivas para compilar apenas o código ao executar como um aplicativo UWP:

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

Observação

NETFX_CORE destina-se apenas a verificar se você está compilando o código C# no back-end de script do .NET. Se você estiver usando um back-end de script diferente, como IL2CPP, use ENABLE_WINMD_SUPPORT em vez disso.

Problemas comuns e soluções alternativas

Os cenários a seguir descrevem problemas comuns que podem surgir quando as APIs do .NET estão ausentes do subconjunto UWP e maneiras de contorná-los.

Serialização de dados usando BinaryFormatter

É comum que os jogos serializem os dados salvos para que os jogadores não possam manipulá-los facilmente. No entanto, BinaryFormatter, que serializa um objeto em binário, não está disponível em versões anteriores do .NET Standard (anteriores à 2.0). Em vez disso, considere usar 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();
}

Operações de E/S

Alguns tipos no namespace System.IO , como FileStream, não estão disponíveis em versões anteriores do .NET Standard. No entanto, o Unity fornece os tipos Directory, File e FileStream para que você possa usá-los em seu jogo.

Como alternativa, você pode usar as APIs Windows.Storage , que só estão disponíveis para aplicativos UWP. No entanto, essas APIs restringem o aplicativo a gravar em seu armazenamento específico e não fornecem acesso gratuito a todo o sistema de arquivos. Consulte Arquivos, pastas e bibliotecas para obter mais informações.

Uma observação importante é que o método Close só está disponível no .NET Standard 2.0 e posterior (embora o Unity forneça um método de extensão). Em vez disso, use Descartar .

Threading

Alguns tipos nos namespaces System.Threading , como ThreadPool, não estão disponíveis em versões anteriores do .NET Standard. Nesses casos, você pode usar o namespace Windows.System.Threading .

Veja como você pode lidar com o threading em um jogo do Unity, usando a compilação dependente da plataforma para se preparar para plataformas UWP e não UWP:

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

Segurança

Alguns dos System.Security.* namespaces, como System.Security.Cryptography.X509Certificates, não estão disponíveis quando você cria um jogo do Unity para UWP. Nesses casos, use o Windows.Security.* APIs, que cobrem grande parte da mesma funcionalidade.

O exemplo a seguir simplesmente obtém os certificados de um repositório de certificados com o nome fornecido:

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
    }

Consulte Segurança para obter mais informações sobre como usar as APIs de segurança do WinRT.

Rede

Alguns dos System.Net.* namespaces, como System.Net.Mail, também não estão disponíveis ao criar um jogo do Unity para UWP. Para a maioria dessas APIs, use o Windows.Networking correspondente .* e Windows.Web.* APIs do WinRT para obter funcionalidade semelhante. Consulte Rede e serviços Web para obter mais informações.

No caso de System.Net.Mail, use o namespace Windows.ApplicationModel.Email . Consulte Enviar email para obter mais informações.

Confira também