整合資產提供功能 (Unity)

整合資產提供功能時,Unity 遊戲可以使用 Addressable 或 AssetBundle 存取資產包。Addressable 是我們最近建議使用的資產提供解決方案,適用於使用 Unity 2019.4 以上版本建構的遊戲,而 AssetBundle 則支援 Unity 2017.4 和 2018.4 中的資產包。

Unity Addressable

若是使用 Unity 2019.4 以上版本建構的遊戲,應使用 Addressable 在 Android 上提供資產。Unity 提供 Play Asset Delivery (PAD) API,以便使用 Addressable 處理 Android 資產包。如要瞭解如何使用 Addressable,請參閱下列資源:

使用 AssetBundle 檔案

若是使用 Unity 2017.4 和 2018.4 建構的遊戲,可以使用 AssetBundle 檔案在 Android 上提供資產。Unity 的 AssetBundle 檔案具有序列化的資產,可在應用程式執行時由 Unity 引擎載入。這些檔案依平台而異 (例如專為 Android 建構的檔案),可與資產包搭配使用。大多數情況下,一個 AssetBundle 檔案會封裝成單一資產包,以及名稱與 AssetBundle 相同的套件。如果想更靈活地建立資產包,請使用 API 設定資產包。

請在執行階段,使用 Unity 專屬 Play Asset Delivery 類別擷取封裝於資產包內的 AssetBundle。

必要條件

  1. 設定開發環境:

OpenUPM-CLI

如果您已安裝 OpenUPM CLI,可以使用下列指令安裝 OpenUPM 登錄:

openupm add com.google.play.assetdelivery

OpenUPM

  1. 選取 Unity 選單選項「Edit」>「Project Settings」>「Package Manager」,開啟套件管理工具設定

  2. 將 OpenUPM 新增為 Package Manager 視窗中的有範圍限制的登錄檔:

    Name: package.openupm.com URL: https://package.openupm.com Scopes: com.google.external-dependency-manager   com.google.play.common   com.google.play.core   com.google.play.assetdelivery   com.google.android.appbundle 
  3. 選取 Unity 選單選項「Window」>「Package Manager」,即可開啟「package manager」選單。

  4. 將管理員範圍下拉式選單設為「我的註冊中心」

  5. 從套件清單中選取「Google Play Integrity 外掛程式 (適用於 Unity)」套件,然後按下「Install」

從 GitHub 匯入

  1. 從 GitHub 下載最新的 .unitypackage 版本。

  2. 選取 Unity 選單選項「Assets」>「Import package」>「Custom Package」,然後匯入所有項目,即可匯入 .unitypackage 檔案。

  1. 在 Unity 中建立 AssetBundle

透過 UI 設定 AssetBundle

  1. 設定資產包中的各項 AssetBundle:

    1. 依序選取「Google」>「Android App Bundle」>「Asset Delivery Settings」
    2. 若要直接選取含有 AssetBundle 檔案的資料夾,請按一下「Add Folder」

  2. 將每個套件的「Delivery Mode」變更為「Install Time」、「Fast Follow」或「On Demand」。解決任何錯誤或依附元件,接著關閉視窗。

  3. 依序選取「Google」>「Build Android App Bundle」,建立應用程式套件。

  4. (選用) 調整應用程式套件的設定,支援不同的紋理壓縮格式

使用 API 設定資產包

您可以透過編輯器指令碼設定資產提供功能,該指令碼可做為自動建構系統的一部分執行。

請使用 AssetPackConfig 類別,定義要在 Android App Bundle 版本中加入哪些資產,並定義資產提供模式。這些資產包不需要包含 AssetBundle。

public void ConfigureAssetPacks {    // Creates an AssetPackConfig with a single asset pack, named    // examplePackName, containing all the files in path/to/exampleFolder.    var assetPackConfig = new AssetPackConfig();    assetPackConfig.AddAssetsFolder("examplePackName",                                    "path/to/exampleFolder",                                    AssetPackDeliveryMode.OnDemand);     // Configures the build system to use the newly created assetPackConfig when    // calling Google > Build and Run or Google > Build Android App Bundle.    AssetPackConfigSerializer.SaveConfig(assetPackConfig);     // Alternatively, use BundleTool.BuildBundle to build an App Bundle from script.    BuildBundle(new buildPlayerOptions(), assetPackConfig); }

您也可以使用 Bundletool 類別中的靜態 BuildBundle 方法,產生內含資產包的 Android App Bundle,但前提是要有 BuildPlayerOptionsAssetPackConfig

如需輔助教學文件,請參閱在 Unity 遊戲程式碼研究室中使用 Play Asset Delivery 一文。

與 Play Asset Delivery Unity API 整合

Play Asset Delivery Unity API 提供的功能包括要求資產包、管理下載內容及存取資產等。請務必先將 Unity 外掛程式新增至專案。

您使用 API 的功能取決於您建立資產包的方式。

如果您使用外掛程式 UI 建立資產包,請選取「外掛程式設定的資產包」

如果您使用 API (或外掛程式 UI) 建立資產包,請選取「API 設定的資產包」

您可以根據想要存取的資產包的傳遞類型來實作 API。步驟請參見下方流程圖。

外掛程式的資產包流程圖

圖 1. 存取資產包的流程圖

擷取 AssetBundle

匯入 Play Asset Delivery 程式庫並呼叫 RetrieveAssetBundleAsync() 方法,以擷取 AssetBundle。

using Google.Play.AssetDelivery;  // Loads the AssetBundle from disk, downloading the asset pack containing it if necessary. PlayAssetBundleRequest bundleRequest = PlayAssetDelivery.RetrieveAssetBundleAsync(asset-bundle-name);

安裝時提供

設定為 install-time 的資產包可在應用程式啟動時立即使用。您可以使用以下方法從 AssetBundle 載入一種情境:

AssetBundle assetBundle = bundleRequest.AssetBundle;  // You may choose to load scenes from the AssetBundle. For example: string[] scenePaths = assetBundle.GetAllScenePaths(); SceneManager.LoadScene(scenePaths[path-index]);

快速追蹤及隨選傳遞

這部分的內容適用於 fast-followon-demand 資產包。

檢查狀態

每個資產包會儲存在應用程式內部儲存空間的獨立資料夾中。使用 isDownloaded() 方法判斷是否已下載資產包。

監控下載內容

查詢 PlayAssetBundleRequest 物件以監控要求的狀態:

// Download progress of request, between 0.0f and 1.0f. The value will always be // 1.0 for assets delivered as install-time. // NOTE: A value of 1.0 will only signify the download is complete. It will still need to be loaded. float progress = bundleRequest.DownloadProgress;  // Returns true if: //   * it had either completed the download, installing, and loading of the AssetBundle, //   * OR if it has encountered an error. bool done = bundleRequest.IsDone;  // Returns status of retrieval request. AssetDeliveryStatus status = bundleRequest.Status; switch(status) {     case AssetDeliveryStatus.Pending:         // Asset pack download is pending - N/A for install-time assets.     case AssetDeliveryStatus.Retrieving:         // Asset pack is being downloaded and transferred to app storage.         // N/A for install-time assets.     case AssetDeliveryStatus.Available:         // Asset pack is downloaded on disk but NOT loaded into memory.         // For PlayAssetPackRequest(), this indicates that the request is complete.     case AssetDeliveryStatus.Loading:         // Asset pack is being loaded.     case AssetDeliveryStatus.Loaded:         // Asset pack has finished loading, assets can now be loaded.         // For PlayAssetBundleRequest(), this indicates that the request is complete.     case AssetDeliveryStatus.Failed:         // Asset pack retrieval has failed.     case AssetDeliveryStatus.WaitingForWifi:         // Asset pack retrieval paused until either the device connects via Wi-Fi,         // or the user accepts the PlayAssetDelivery.ShowConfirmationDialog dialog.     case AssetDeliveryStatus.RequiresUserConfirmation:         // Asset pack retrieval paused until the user accepts the         // PlayAssetDelivery.ShowConfirmationDialog dialog.     default:         break; }

大型下載內容

大小超過 200 MB 的資產包只有在與 Wi-Fi 連線時才會自動下載。如果使用者未連上 Wi-Fi,PlayAssetBundleRequest 狀態會設為 AssetDeliveryStatus.WaitingForWifi,下載作業也會暫停。在此情況下,請等到裝置連線至 Wi-Fi 後再繼續下載,或提示使用者允許透過行動網路連線下載資產包。

需要使用者確認

如果套件具有 AssetDeliveryStatus.RequiresUserConfirmation 狀態,使用者必須接受顯示 PlayAssetDelivery.ShowConfirmationDialog() 的對話方塊,下載作業才會繼續進行。如果 Play 無法辨識應用程式,就會出現這個狀態。請注意,在這種情況下呼叫 PlayAssetDelivery.ShowConfirmationDialog() 會導致應用程式更新。更新完成後,請再次要求素材資源。

if(request.Status == AssetDeliveryStatus.RequiresUserConfirmation    || request.Status == AssetDeliveryStatus.WaitingForWifi) {     var userConfirmationOperation = PlayAssetDelivery.ShowConfirmationDialog();     yield return userConfirmationOperation;      switch(userConfirmationOperation.GetResult()) {         case ConfirmationDialogResult.Unknown:             // userConfirmationOperation finished with an error. Something went             // wrong when displaying the prompt to the user, and they weren't             // able to interact with the dialog.         case ConfirmationDialogResult.Accepted:             // User accepted the confirmation dialog--an update will start.         case ConfirmationDialogResult.Declined:             // User canceled or declined the dialog. It can be shown again.         default:             break;     } }

取消要求 (僅限隨選)

若要在 AssetBundle 載入記憶體之前取消要求,請在 PlayAssetBundleRequest 物件上呼叫 AttemptCancel() 方法:

// Will only attempt if the status is Pending, Retrieving, or Available - otherwise // it will be a no-op. bundleRequest.AttemptCancel();  // Check to see if the request was successful by checking if the error code is Canceled. if(bundleRequest.Error == AssetDeliveryErrorCode.Canceled) {     // Request was successfully canceled. }

以非同步方式要求資產包

在多數情況下,您應使用協同程式,以非同步方式要求資產包並監控進度,如下所示:

private IEnumerator LoadAssetBundleCoroutine(string assetBundleName) {      PlayAssetBundleRequest bundleRequest =         PlayAssetDelivery.RetrieveAssetBundleAsync(assetBundleName);      while (!bundleRequest.IsDone) {         if(bundleRequest.Status == AssetDeliveryStatus.WaitingForWifi) {             var userConfirmationOperation = PlayAssetDelivery.ShowCellularDataConfirmation();              // Wait for confirmation dialog action.             yield return userConfirmationOperation;              if((userConfirmationOperation.Error != AssetDeliveryErrorCode.NoError) ||                (userConfirmationOperation.GetResult() != ConfirmationDialogResult.Accepted)) {                 // The user did not accept the confirmation. Handle as needed.             }              // Wait for Wi-Fi connection OR confirmation dialog acceptance before moving on.             yield return new WaitUntil(() => bundleRequest.Status != AssetDeliveryStatus.WaitingForWifi);         }          // Use bundleRequest.DownloadProgress to track download progress.         // Use bundleRequest.Status to track the status of request.          yield return null;     }      if (bundleRequest.Error != AssetDeliveryErrorCode.NoError) {         // There was an error retrieving the bundle. For error codes NetworkError         // and InsufficientStorage, you may prompt the user to check their         // connection settings or check their storage space, respectively, then         // try again.         yield return null;     }      // Request was successful. Retrieve AssetBundle from request.AssetBundle.     AssetBundle assetBundle = bundleRequest.AssetBundle;

若要進一步瞭解如何處理錯誤,請參閱 AssetDeliveryErrorCodes 清單。

其他 Play Core API 方法

以下列出一些其他您可能想在應用程式中使用的 API 方法。

檢查下載內容的大小

如要檢查 AssetBundle 大小,請對 Google Play 發出非同步呼叫,並設定作業完成後的回呼方法:

public IEnumerator GetDownloadSize() {    PlayAsyncOperation<long> getSizeOperation =    PlayAssetDelivery.GetDownloadSize(assetPackName);     yield return getSizeOperation;    if(operation.Error != AssetDeliveryErrorCode.NoError) {        // Error while retrieving download size.     } else {         // Download size is given in bytes.         long downloadSize = operation.GetResult();     } }

移除 AssetBundle

您可以移除目前尚未載入記憶體的快速追蹤及隨選 AssetBundle。請進行以下非同步呼叫,並設定完成時的回呼方法:

PlayAsyncOperation<string> removeOperation = PlayAssetDelivery.RemoveAssetPack(assetBundleName);  removeOperation.Completed += (operation) =>             {                 if(operation.Error != AssetDeliveryErrorCode.NoError) {                     // Error while attempting to remove AssetBundles.                 } else {                     // Files were deleted OR files did not exist to begin with.                 }             };

後續步驟

在本機和 Google Play 中測試 Asset Delivery