Unity や UWP で不足している .NET API

.NET を使用して UWP ゲームを作成する場合、Unity エディターで使用できる一部の API やスタンドアロン PC ゲーム用の一部の API が UWP 用に存在しないことがあります。 これは、UWP アプリ用 .NET には、名前空間ごとに、フル バージョンの .NET Framework で提供される型のサブセットが含まれるためです。

さらに、Unity の Mono など一部のゲーム エンジンは、UWP 用の .NET とは完全な互換性のない別の種類の .NET を使用しています。 したがって、ゲームを作成する際に、エディターでは問題なく動作しても、UWP 用にビルドすると、"型または名前空間の名前 'Formatters' は名前空間 'System.Runtime.Serialization' に存在しません (アセンブリ参照があることを確認してください)" というエラーが出力される可能性があります。

幸いなことに、Unity では、これらの不足している API の一部を拡張メソッドや置換型として提供しています。詳しくは、ユニバーサル Windows プラットフォームの .NET Scripting Backend で不足している .NET 型に関するページをご覧ください。 ただし、必要な機能がここにない場合は、Windows 8.x アプリ用 .NET の概要に関するページで説明している方法に従って、WinRT または Windows ランタイム API 用 .NET を使用するようにコードを変換できます (このページでは、Windows 8 について説明していますが、Windows 10 の UWP アプリにも適用できます)。

.NET Standard

一部の API が動作しない理由を理解するには、.NET のさまざまな種類と、UWP での .NET の実装方法を理解しておく必要があります。 .NET Standard は、クロスプラットフォームに対応し、さまざまな種類の .NET を統一することを目的とした、.NET API の正式な仕様です。 .NET の各実装では、特定のバージョンの .NET Standard をサポートしています。 標準や実装の一覧表については、「.NET 実装のサポート」をご覧ください。

UWP SDK の各バージョンは、.NET Standard のさまざまなレベルに準拠しています。 たとえば、16299 SDK (Fall Creators Update) では、.NET Standard 2.0 をサポートしています。

ターゲットにしている UWP バージョンで特定の .NET API がサポートされるかどうかを確認する場合は、.NET Standard API リファレンスを参照して、そのバージョンの UWP でサポートされている .NET Standard のバージョンを選択します。

スクリプト バックエンドの構成

UWP のビルドで問題が発生した場合に最初に行うことは、[Player Settings] (プレーヤーの設定) ([File] (ファイル) > [Build Settings] (ビルド設定)[Universal Windows Platform] (ユニバーサル Windows プラットフォーム)[Player Settings] (プレーヤーの設定) の順に選択) を確認することです。 [Other Settings] (その他の設定) > [Configuration] (構成) にある、最初の 3 つのドロップダウン リスト ([Scripting Runtime Version] (スクリプト ランタイム バージョン)[Scripting Backend] (スクリプト バックエンド)[Api Compatibility Level] (API 互換性レベル)) はいずれも考慮する必要がある重要な設定です。

[Scripting Runtime Version] (スクリプト ランタイム バージョン) は、Unity スクリプト バックエンドが使用するもので、選択した .NET Framework サポートと (ほぼ) 同等のバージョンを取得できます。 ただし、そのバージョンの .NET Framework のすべての API がサポートされるわけではない点に注意してください。UWP がターゲットにしている .NET Standard のバージョンでサポートされている API のみがサポートされます。

新しい .NET リリースでは、通常、より多くの API が .NET Standard に追加され、スタンドアロンと UWP で同じコードを使用できるようになっている場合があります。 たとえば、System.Runtime.Serialization.Json 名前空間は .NET Standard 2.0 で導入されました。 [Scripting Runtime Version] (スクリプト ランタイム バージョン)[.NET 3.5 Equivalent] (.NET 3.5 相当) (以前のバージョンの .NET Standard をターゲットにする) に設定した場合、API を使用しようとしたときにエラーが表示されます。[.NET 4.6 Equivalent] (.NET 4.6 相当) (.NET Standard 2.0 をサポートする) に切り替えると、API は動作します。

[Scripting Backend] (スクリプト バックエンド) は、[.NET] または [IL2CPP] に設定できます。 このトピックでは、.NET で発生する問題について説明しているため、[.NET] を選択していることを想定しています。 詳細については、スクリプト バックエンドに関するページをご覧ください。

最後に、[Api Compatibility Level] (API 互換性レベル) を、ゲームを実行する .NET のバージョンに設定します。 これは、[Scripting Runtime Version] (スクリプト ランタイム バージョン) と一致している必要があります

一般的に、[Scripting Runtime Version] (スクリプト ランタイム バージョン)[Api Compatibility Level] (API 互換性レベル) については、.NET Framework との互換性を高め、より多くの .NET API を使用できるようにするために、利用可能な最新バージョンを選択してください。

構成: スクリプト ランタイム バージョン、スクリプト バックエンド、API 互換性レベル

プラットフォーム依存のコンパイル

UWP を含む複数のプラットフォーム用に Unity ゲームを作成する場合、ゲームが UWP として作成されたときにのみ、UWP 向けのコードが実行されるようにするために、プラットフォーム依存のコンパイルを使用できます。 これにより、スタンドアロンのデスクトップやその他のプラットフォーム用にフル バージョンの .NET Framework を、UWP 用に WinRT API を使用でき、ビルド エラーが発生することはありません。

UWP アプリとして実行する場合にのみコードをコンパイルするには、次のディレクティブを使用します。

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

注意

NETFX_COREは、.NET スクリプト バックエンドに対して C# コードをコンパイルするかどうかをチェックするためのものです。 IL2CPP などの別のスクリプト バックエンドを使用している場合は、代わりに ENABLE_WINMD_SUPPORT を使用します。

一般的な問題と対処法

次のシナリオでは、UWP のサブセットに .NET API がない場合に発生する可能性がある一般的な問題と、それらを回避する方法について説明します。

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

I/O 操作

System.IO 名前空間の一部の型 (FileStream など) は、以前のバージョンの .NET Standard では使用できません。 ただし、Unity では、DirectoryFile、および FileStream 型を提供しているため、ゲームでこれらを使用できます。

また、UWP アプリでのみ利用できる Windows.Storage API を使用することもできます。 ただし、これらの API では、アプリの書き込みは特定の記憶域に制限され、ファイル システム全体に自由にアクセスすることはできません。 詳しくは、「ファイル、フォルダー、およびライブラリ」をご覧ください。

重要な注意事項は、Close メソッドは、.NET Standard 2.0 以降でのみ利用できることです (ただし、Unity は拡張メソッドを提供しています)。 代わりに、Dispose を使用します。

スレッド

System.Threading 名前空間の一部の型 (ThreadPool など) は、以前のバージョンの .NET Standard では使用できません。 このような場合は、代わりに Windows.System.Threading 名前空間を使用できます。

以下に、プラットフォーム依存のコンパイルを使用し、UWP と UWP 以外の両方のプラットフォーム用に準備して、Unity ゲームでスレッド化を処理する方法を示します。

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 など) は、UWP 用に Unity ゲームを構築する場合は利用できません。 このような場合は、同じ機能の多くをカバーしている Windows.Security.* API を使用します。

次の例では、指定した名前の証明書ストアからの証明書だけを取得します。

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
    }

WinRT セキュリティ API の使用方法の詳細については、「セキュリティ」を参照してください。

ネットワーク

System.Net.* 名前空間の一部 (System.Net.Mail など) も、UWP 用に Unity ゲームを構築する場合は利用できません。 これらの API のほとんどについては、対応する Windows.Networking.* と Windows.Web.* WinRT API を使用して同様の機能を実現できます。 詳細については、「ネットワークと Web サービス」を参照してください。

System.Net.Mail の場合は、Windows.ApplicationModel.Email 名前空間を使用します。 詳細については、「メールの送信」を参照してください。

こちらもご覧ください