封裝通用 Windows 平台 (UWP) DirectX 遊戲

大型通用 Windows 平台 (UWP) 遊戲,特別是支援具有區域特定資產或功能選擇性高定義資產的多種語言的遊戲,可以輕鬆地膨脹為大型大小。 在本主題中,瞭解如何使用應用程式套件和應用程式套件組合來自訂您的應用程式,讓您的客戶只接收他們實際需要的資源。

除了應用程式套件模型之外,Windows 10 還支援將兩種類型的套件組合在一起的應用程式套件組合:

  • 應用程式套件包含平台特定的可執行檔和程式庫。 一般而言,UWP 遊戲最多可以有三個應用程式套件:x86、x64 和 Arm CPU 架構各有一個。 該硬體平台專屬的所有程式碼和資料都必須包含在其應用程式套件中。 應用程式套件也應該包含遊戲的所有核心資產,以基準層級的逼真度和效能執行。
  • 資源套件包含選擇性或擴充的平台無關資料,例如遊戲資產 (紋理、網格、音效、文字)。 UWP 遊戲可以有一或多個資源套件,包括高畫質資產或紋理的資源套件、DirectX 功能層級 11+ 資源,或語言特定的資產和資源。

如需應用程式套件組合和應用程式套件的詳細資訊,請參閱定義應用程式資源

雖然您可以將所有內容放入應用程式套件中,但這是低效且多餘的。 為什麼每個平台都會有相同的大型紋理檔案複製三次,尤其是可能未使用它的 Arm 平台? 一個好的目標是盡量減少客戶必須下載的內容,以便他們可以更快地開始玩您的遊戲,節省裝置空間,並避免可能的計量頻寬成本。

若要使用 UWP 應用程式安裝程式的這項功能,請務必在遊戲開發初期考慮應用程式和資源封裝的目錄配置和資源命名慣例,讓工具和來源可以正確地輸出它們,讓封裝變得簡單。 在開發或設定資產建立和管理工具和指令碼,以及撰寫載入或參考資源的程式碼時,請遵循此文件中所述的規則。

為何要建立資源套件?

當您建立應用程式,特別是可在許多地區設定或各種 UWP 硬體平台中銷售的遊戲應用程式時,您通常需要包含多個版本的許多檔案,以支援這些地區設定或平台。 例如,如果您要在美國和日本中發佈遊戲,則 en-us 地區設定可能需要一組英文語音檔案,而 jp-jp 地區設定則需要另一組日文語音檔案。 或者,如果您想要在遊戲中使用適用於 Arm 裝置和 x86 和 x64 平台的影像,則必須針對每個 CPU 架構上傳相同的影像資產 3 次。

此外,如果您的遊戲有許多高畫質資源不適用於較低 DirectX 功能層級的平台,為什麼將它們包含在基準應用程式套件中,並要求您的使用者下載大量裝置無法使用的元件? 將這些高解析度資源分成可選的資源套件,意味著擁有支援這些高解析度資源的裝置的客戶可以以 (可能是計量的) 頻寬為代價獲得它們,而沒有更高端裝置的客戶可以獲得他們的遊戲更快且網路使用成本更低。

遊戲資源套件的內容候選項目包括:

  • 國際地區設定特定資產 (當地語系化的文字、音訊或影像)
  • 適用於不同裝置縮放比例 (1.0x、1.4x 和 1.8x) 的高解析度資產
  • 適用於較高 DirectX 功能層級 (9、10 和 11) 的高定義資產

這一切都定義在屬於 UWP 專案的 package.appxmanifest 中,以及最終套件的目錄結構中。 由於新的 Visual Studio UI,如果您遵循本文件中的程序,就不需要手動編輯它。

重要事項:這些資源的載入和管理是透過 Windows.ApplicationModel.Resources* API 處理的。 如果您使用這些應用程式模型資源 API 來載入區域設定、縮放比例或 DirectX 功能層級的正確文件,則無需使用明確文件路徑載入資源;相反地,您只向資源 API 提供所需資產的通用檔案名稱,並讓資源管理系統取得適合使用者目前平台和區域設定配置的資源的正確變體 (您也可以使用這些直接指定) 相同的 API)。

資源封裝的資源會以下列兩種基本方式之一指定:

  • 資產檔案具有相同的檔名,而資源套件特定版本會放在特定的具名目錄中。 系統會保留這些目錄名稱。 例如,\en-us、\scale-140、\dxfl-dx11。
  • 資產檔案會以任意名稱儲存在資料夾中,但檔案會以通用標籤命名,並附加系統保留的字串來表示語言或其他限定詞。 具體來說,限定詞字串會貼到底線之後的一般化檔名 (“_”)。 例如,\assets\menu_option1_lang-en-us.png、\assets\menu_option1_scale-140.png、\assets\coolsign_dxfl-dx11.dds。 您也可以合併這些字串。 例如,\assets\menu_option1_scale-140_lang-en-us.png。

    注意:當用於檔案名稱而不是單獨用於目錄名稱時,語言限定詞必須採用「lang-<tag>」形式,例如「lang-en-us」,如針針對語言、縮放比例和其他限定詞量身打造資源中所述。

您可以結合目錄名稱,以取得資源封裝中的其他特定性。 不過,它們不可以是多餘的。 例如,\en-us\menu_option1_lang-en-us.png 是多餘的。

只要每個資源目錄中的目錄結構相同,您就可以在資源目錄下指定任何您需要的非保留子目錄名稱。 例如,\dxfl-dx10\assets\textures\coolsign.dds。 當您載入或參考資產時,路徑名稱必須一般化、移除語言、縮放比例或 DirectX 功能層級的任何限定詞,不論它們位於資料夾節點或檔名中。 例如,若要在程式碼中參考其中一個變體為 \dxfl-dx10\assets\textures\coolsign.dds 的資產,請使用 \assets\textures\coolsign.dds。 同樣地,若要參考具有 variant \images\background_scale-140.png 的資產,請使用 \images\background.png。

以下是下列保留的目錄名稱和檔名底線前置詞:

資產類型 資源套件目錄名稱 資源套件檔名尾碼
當地語系化的資產 Windows 10 的所有可能語言或語言和地區設定組合。 (資料夾名稱中不需要限定詞前置詞「lang-」。) 後面接著語言、地區設定或語言地區設定規範的「_」。 例如,「_en」、「_us」或「_en-us」。
縮放比例資產 scale-100、scale-140、scale-180。 這些分別適用於 1.0x、1.4x 和 1.8x UI 縮放比例。 「_」後面接著「scale-100」、「scale-140」或「scale-180」。
DirectX 功能層級資產 dxfl-dx9、dxfl-dx10 和 dxfl-dx11。 這些分別適用於 DirectX 9、10 和 11 功能層級。 「_」後面接著「dxfl-dx9」、「dxfl-dx10」或「dxfl-dx11」。。

 

定義當地語系化的語言資源套件

地區設定特定的檔案會放在以語言命名的專案目錄中 (例如,「en」)。

設定您的應用程式以支援多種語言的當地語系化資產時,您應該:

  • 針對您將支援的每個語言和地區設定建立應用程式子目錄 (或檔案版本) (例如 en-us、jp-jp、zh-cn、fr-fr 等等)。

  • 在開發期間,將 ALL 資產的複本 (例如當地語系化的音訊檔案、紋理和功能表圖形) 放在對應的語言地區設定子目錄中,即使它們與語言或地區設定不同也一樣。 為獲得最佳使用者體驗,如果使用者尚未取得其地區設定的可用語言資源套件,請確定他們有可用的語言資源套件可供使用 (或者如果他們在下載和安裝之後不小心將其刪除)。

  • 請確定每個資產或字串資源檔案 (.resw) 在每個目錄中都有相同的名稱。 例如,menu_option1.png 應該在 \en-us 和 \jp-jp 目錄中具有相同的名稱,即使檔案的內容適用於不同的語言也一樣。 在此情況下,您會看到它們為 \en-us\menu_option1.png 和 \jp-jp\menu_option1.png。

    注意:您可以選擇性地將地區設定附加至檔名,並將其儲存在相同的目錄中;例如\assets\menu_option1_lang-en-us.png、\assets\menu_option1_lang-jp-jp.png。

     

  • 使用 Windows.ApplicationModel.ResourcesWindows.ApplicationModel.Resources.Core 中的 API 為您的應用程式指定和載入特定於區域設定的資源。 此外,請使用不包含特定地區設定的資產參考,因為這些 API 會根據使用者的設定決定正確的地區設定,然後擷取使用者的正確資源。

  • 在 Microsoft Visual Studio 2015 中,選取 PROJECT->Store->Create App Package...,然後建立套件。

定義縮放比例資源套件

Windows 10 提供三個使用者介面縮放比例:1.0x、1.4x 和 1.8x。 每個顯示器的縮放比例值都會根據一些組合因素來設定:螢幕大小、螢幕解析度,以及使用者與螢幕的平均距離。 使用者也可以調整縮放比例,以改善可讀性。 您的遊戲應該是 DPI 感知和縮放比例感知,以獲得最佳體驗。 此感知的一部分表示針對這三個縮放比例的每個建立重要視覺資產版本。 這也包括指標互動和點擊測試!

設定您的應用程式以支援不同 UWP 應用程式縮放比例的資源套件時,您應該:

  • 針對您將支援的每個縮放比例建立應用程式子目錄 (或檔案版本) (scale-100、scale-140 和 scale-180)。

  • 在開發期間,在每一個縮放比例資源目錄中放置所有資產的縮放比例適當複本,即使這些資產在縮放比例之間沒有不同也一樣。

  • 請確保每個資產在每個目錄中都有相同的名稱。 例如,即使檔案的內容不同,menu_option1.png 在 \scale-100 和 \scale-180 目錄中應該具有相同的名稱。 在此情況下,您會將其視為 \scale-100\menu_option1.png 和 \scale-140\menu_option1.png。

    注意:同樣地,您可以選擇性地將縮放比例尾碼附加至檔名,並將其儲存在相同的目錄中;例如\assets\menu_option1_scale-100.png\assets\menu_option1_scale-140.png。

     

  • 使用 Windows.ApplicationModel.Resources.Core 中的 API 來載入資產。 資產參考應一般化 (無尾碼),以排除特定的縮放比例變化。 系統會擷取顯示和使用者設定的適當縮放比例資產。

  • 在 Microsoft Visual Studio 2015 中,選取 PROJECT->Store->Create App Package...,然後建立套件。

定義 DirectX 功能層級資源套件

DirectX 功能層級會對應至舊版和目前 DirectX 的 GPU 功能集 (特別是 Direct3D)。 這包括著色器模型規格和功能、著色器語言支援、紋理壓縮支援,以及整體圖形管線功能。

您的基準應用程式套件應該使用基準紋理壓縮格式:BC1、BC2 或 BC3。 任何 UWP 裝置都可以使用這些格式,從低端 Arm 平台到專用的多 GPU 工作站和媒體電腦。

應該在資源套件中新增 DirectX 功能層級 10 或更新版本的紋理格式支援,以節省本機磁碟空間和下載頻寬。 這可讓您針對 11 使用更進階的壓縮配置,例如 BC6H 和 BC7。 (如需詳細資訊,請參閱 Direct3D 11 中的紋理區塊壓縮。) 這些格式對於新式 GPU 支援的高解析度紋理資產更有效率,而且使用這些格式可改善遊戲在高端平台上的外觀、效能和空間需求。

DirectX 功能層級 支援的紋理壓縮
9 BC1、BC2、BC3
10 BC4、BC5
11 BC6H、BC7

 

此外,每個 DirectX 功能層級都支援不同的著色器模型版本。 編譯的著色器資源可以根據每個功能層級建立,而且可以包含在 DirectX 功能層級資源套件中。 此外,某些較新的版本著色器模型可以使用資產,例如一般對應,而舊版著色器模型版本則無法使用。 這些著色器模型特定資產也應該包含在 DirectX 功能層級資源套件中。

資源機制主要著重於資產支援的紋理格式,因此僅支援 3 個整體功能層級。 如果您需要針對子層級 (點版本) 有個別的著色器,例如 DX9_1 與 DX9_3,您的資產管理和轉譯程式碼必須明確地處理它們。

設定您的應用程式以支援不同 DirectX 功能層級的資源套件時,您應該:

  • 針對您將支援的每個 DirectX 功能層級建立應用程式子目錄 (或檔案版本) (dxfl-dx9、dxfl-dx10 和 dxfl-dx11)。

  • 在開發期間,將功能層級特定資產放在每個功能層級資源目錄中。 不同於地區設定和縮放比例,遊戲中的每個功能層級可能會有不同的轉譯程式碼分支,而且如果您有紋理、已編譯的著色器或其他只用於一或所有支援功能層級子集的資產,請將對應的資產只放在使用它們之功能層級的目錄中。 針對跨所有功能層級載入的資產,請確定每個功能層級資源目錄都有相同名稱的版本。 例如,對於名為「coolsign.dds」的功能層級獨立紋理,請將 BC3 壓縮版本放在 \dxfl-dx9 目錄中,並將 BC7 壓縮的版本放在 \dxfl-dx11 目錄中。

  • 請確保每個資產 (如果可供多個功能層級使用) 在每個目錄中都有相同的名稱。 例如,即使檔案的內容不同,coolsign.dds在 \dxfl-dx9 和 \dxfl-dx11 目錄中應該具有相同的名稱。 在此情況下,您會將其視為 \dxfl-dx9\coolsign.dds 和 \dxfl-dx11\coolsign.dds。

    注意:同樣地,您可以選擇性地將功能層級尾碼附加至檔名,並將其儲存在相同的目錄中;例如,\textures\coolsign_dxfl-dx9.dds\textures\coolsign_dxfl-dx11.dds。

     

  • 設定圖形資源時,宣告支援的 DirectX 功能層級。

    D3D_FEATURE_LEVEL featureLevels[] = 
    {
      D3D_FEATURE_LEVEL_11_1,
      D3D_FEATURE_LEVEL_11_0,
      D3D_FEATURE_LEVEL_10_1,
      D3D_FEATURE_LEVEL_10_0,
      D3D_FEATURE_LEVEL_9_3,
      D3D_FEATURE_LEVEL_9_1
    };
    
    ComPtr<ID3D11Device> device;
    ComPtr<ID3D11DeviceContext> context;
    D3D11CreateDevice(
        nullptr,                    // Use the default adapter.
        D3D_DRIVER_TYPE_HARDWARE,
        0,                      // Use 0 unless it is a software device.
        creationFlags,          // defined above
        featureLevels,          // What the app will support.
        ARRAYSIZE(featureLevels),
        D3D11_SDK_VERSION,      // This should always be D3D11_SDK_VERSION.
        &device,                    // created device
        &m_featureLevel,            // The feature level of the device.
        &context                    // The corresponding immediate context.
    );
    
  • 使用 Windows.ApplicationModel.Resources.Core 中的 API 來載入資源。 資產參考應該一般化 (無尾碼),以省略功能層級。 不過,不同於語言和縮放比例,系統不會自動判斷哪一個功能層級最適合指定的顯示器;這是留給您根據程式碼邏輯來判斷的。 進行該判斷之後,請使用 API 通知 OS 偏好的功能層級。 然後,系統將能夠根據該喜好設定擷取正確的資產。 以下是一個程式碼範例,示範如何通知您的應用程式平台目前的 DirectX 功能層級:

    // Set the current UI thread's MRT ResourceContext's DXFeatureLevel with the right DXFL. 
    
    Platform::String^ dxFeatureLevel;
        switch (m_featureLevel)
        {
        case D3D_FEATURE_LEVEL_9_1:
        case D3D_FEATURE_LEVEL_9_2:
        case D3D_FEATURE_LEVEL_9_3:
            dxFeatureLevel = L"DX9";
            break;
        case D3D_FEATURE_LEVEL_10_0:
        case D3D_FEATURE_LEVEL_10_1:
            dxFeatureLevel = L"DX10";
            break;
        default:
            dxFeatureLevel = L"DX11";
        }
    
        ResourceContext::SetGlobalQualifierValue(L"DXFeatureLevel", dxFeatureLevel);
    

注意

在您的程式碼中,以名稱直接載入紋理 (或功能層級目錄下方的路徑)。 請勿包含功能層級目錄名稱或尾碼。 例如,載入「textures\coolsign.dds」,而不是「dxfl-dx11\textures\coolsign.dds」或「textures\coolsign_dxfl-dx11.dds」。

  • 現在使用 ResourceManager 尋找與目前 DirectX 功能層級相符的檔案。 ResourceManager 傳回一個 ResourceMap,您可以使用 ResourceMap::GetValue (或 ResourceMap::TryGetValue) 和提供的 ResourceContext 來查詢它。 這將傳回與透過呼叫 SetGlobalQualifierValue 指定的 DirectX 功能層級最符合的 ResourceCandidate

    // An explicit ResourceContext is needed to match the DirectX feature level for the display on which the current view is presented.
    
    auto resourceContext = ResourceContext::GetForCurrentView();
    auto mainResourceMap = ResourceManager::Current->MainResourceMap;
    
    // For this code example, loader is a custom ref class used to load resources.
    // You can use the BasicLoader class from any of the 8.1 DirectX samples similarly.
    
    
    auto possibleResource = mainResourceMap->GetValue(
        L"Files/BumpPixelShader.cso",
        resourceContext
    );
    Platform::String^ resourceName = possibleResource->ValueAsString;
    
  • 在 Microsoft Visual Studio 2015 中,選取 PROJECT->Store->Create App Package...,然後建立套件。

  • 請確保您在 package.appxmanifest 指令清單設定中啟用應用程式套件組合。