Unity 和 UWP 中遺失 .NET API

使用 .NET 建置 UWP 遊戲時,您可能會發現您可能在 Unity 編輯器中,或用於獨立 PC 遊戲的某些 API 不適用於 UWP。 這是因為 UWP 應用程式的 .NET,包含完整 .NET Framework 中為每個命名空間提供的類型的子集。

此外,某些遊戲引擎會使用不同風格的 .NET,這些與 UWP 的 .NET 不完全相容,例如 Unity 的 Mono。 因此,當您編寫遊戲時,一切可能在編輯器中運作正常,但是當您為 UWP 建置時,您可能會收到以下錯誤:名稱空間「System.Runtime.Serialization」中不存在類型或名稱空間「Formatters」(您是否缺少組件參考?)

幸運的是,Unity 提供了一些缺少的 API 做為擴充方法和替換類型,這些在通用 Windows 平台:.NET 指令碼後端上缺少 .NET 類型中進行了描述。 但是,如果此處沒有您需要的功能,適用於 Windows 8.x 應用程式的 .NET 概觀討論了將程式碼轉換為使用 WinRT 或適用於 Windows 執行階段 API 的 .NET 之方法。 (它討論了 Windows 8,但也適用於 Windows 10 UWP 應用程式。)

.NET Standard

若要瞭解為什麼某些 API 可能無法運作,請務必瞭解不同的 .NET 風格以及 UWP 如何實作 .NET。 .NET Standard 是 .NET API 的正式規格,旨在跨平台並統一不同的 .NET 風格。 .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 時遇到問題,您應該做的第一件事是檢查播放器設定 (檔案>建置設定,選取通用 Windows 平台,然後選取播放器設定)。 在其他設定>設定下,前三個下拉式清單 (指令碼執行階段版本指令碼後端Api 相容性層級) 都是需要考慮的重要設定。

指令碼執行階段版本是 Unity 指令碼後端使用的版本,它允許您獲得您選擇的 (大致) 等效版本的 .NET Framework 支援。 不過,請記住,不支援該版本 .NET Framework 中的所有 API,只支援 UWP 的目標 .NET Standard 版本中的 API。

通常,在新的 .NET 版本中,.NET Standard 中會新增更多 API,這可能讓您能在獨立版和 UWP 中使用相同的程式碼。 例如,.NET Standard 2.0 中引入了 System.Runtime.Serialization.Json 命名空間。 如果將指令碼執行階段版本設定為 .NET 3.5 等效版本 (其目標是早期版本的 .NET Standard),則在嘗試使用 API 時將會出現錯誤;將其切換到 .NET 4.6 等效版本 (支援 .NET Standard 2.0),API 將正常運作。

指令碼後端可以是 .NETIL2CPP。 針對本主題,我們假設您已選擇 .NET,因為這是此處討論的問題所在。 請參閱指令碼後端以瞭解更多資訊。

最後,您應該將 Api 相容性層級設定為您希望遊戲執行的 .NET 版本。 這應該符合指令碼執行階段版本

一般來說,對於指令碼執行階段版本Api 相容性層級,您應該選取可用的最新版本,以便與 .NET Framework 具有更高的相容性,進允讓您能使用更多 .NET API。

Configuration: Scripting Runtime Version; Scripting Backend; Api Compatibility Level

平台相依編譯

如果您要為多個平台建置 Unity 遊戲,包括 UWP,您會想要使用平台相依編譯,以確保只有在遊戲建置為 UWP 時,才會執行適用於 UWP 的程式碼。 如此一來,您就可以將完整的 .NET Framework 用於獨立桌面和其他平台,並將 WinRT API 用於 UWP,而不會出現建置錯誤。

使用以下指令詞,僅在做為 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 之前) 中不可用。 請考慮改用 XmlSerializerDataContractJsonSerializer

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 確實提供了 DirectoryFileFileStream類型,因此您可以在遊戲中使用它們。

或者,您可以使用 Windows.Storage,該 API 僅適用於 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
}

安全性

當您為 UWP 建立 Unity 遊戲時,某些 System.Security.* 命名空間,例如 System.Security.Cryptography.X509Certificates,將不可用。 在這些情況下,請使用 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 的詳細資訊,請參閱安全性

網路

為 UWP 建立 Unity 遊戲時,某些 System.Net.* 命名空間,例如 System.Net.Mail,也不可用。 對於大多數這些 API,請使用相應的 Windows.Networking.* 和 Windows.Web.* WinRT API 來獲得類似的功能。 有關詳細資訊,請參閱網路和 Web 服務

對於 System.Net.Mail,請使用 Windows.ApplicationModel.Email 命名空間。 如需詳細資訊,請參閱傳送電子郵件

另請參閱