Integrowanie dostawy zasobów (Unity)

Podczas integrowania przesyłania zasobów gry Unity mogą uzyskiwać dostęp do pakietów zasobów za pomocą adresów lub pakietów zasobów. Adresowalne to najnowsze i zalecane rozwiązanie do dostarczania komponentów w przypadku gier utworzonych w wersji Unity 2019.4 lub nowszej, natomiast pakiety komponentów obsługują pakiety komponentów w wersjach Unity 2017.4 i 2018.4.

Unity Addressables

Gry utworzone w wersji Unity 2019.4 lub nowszej powinny korzystać z adresowalności na potrzeby przesyłania zasobów na Androida. Unity udostępnia interfejs Play Asset Delivery (PAD) do obsługi pakietów zasobów na Androida za pomocą usługi Addressables. Informacje o używaniu adresowalnych reklam znajdziesz w tych materiałach:

Używanie plików AssetBundle

Gry utworzone w Unity 2017.4 i 2018.4 mogą używać plików AssetBundle do dostarczania zasobów na Androida. Pliki AssetBundle w Unity zawierają serializowane zasoby, które mogą być wczytywane przez silnik Unity podczas działania aplikacji. Te pliki są przeznaczone do konkretnej platformy (np. Androida) i można ich używać w połączeniu z pakietami komponentów. Najczęściej jeden plik AssetBundle jest pakowany w jeden pakiet komponentów, który ma tę samą nazwę co plik AssetBundle. Jeśli chcesz mieć większą elastyczność podczas tworzenia pakietu komponentów, skonfiguruj go za pomocą interfejsu API.

W czasie wykonywania kodu użyj klasy Play Asset Delivery for Unity, aby pobrać pakiet AssetBundle zapakowany w pakiet zasobów.

Wymagania wstępne

  1. Skonfiguruj środowisko programistyczne:

OpenUPM-CLI

Jeśli masz zainstalowany interfejs wiersza poleceń OpenUPM, możesz zainstalować rejestr OpenUPM za pomocą tego polecenia:

openupm add com.google.play.assetdelivery

OpenUPM

  1. Otwórz ustawienia menedżera pakietów, klikając opcję menu Unity Edytuj > Ustawienia projektu > Menedżer pakietów.

  2. Dodaj OpenUPM jako ograniczony rejestr do okna Menedżera pakietów:

    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. Otwórz menu menedżera pakietów, wybierając w menu Unity opcję Okno > Menedżer pakietów.

  4. W menu zakresu menedżera wybierz Moje rejestry.

  5. Na liście pakietów wybierz pakiet Google Play Integrity plugin for Unity i kliknij Zainstaluj.

Importowanie z GitHuba

  1. Pobierz najnowszą wersję .unitypackage z GitHuba.

  2. Zaimportuj plik .unitypackage, wybierając opcję menu Unity Zasoby > Importuj pakiet > Własny pakiet i importując wszystkie elementy.

  1. Utwórz pakiety zasobów w Unity.

Konfigurowanie pakietów komponentów za pomocą interfejsu

  1. Skonfiguruj każdy pakiet zasobów w pakiecie zasobów:

    1. Kliknij Google > Pakiet aplikacji na Androida > Ustawienia dostarczania zasobów.
    2. Aby wybrać foldery, które bezpośrednio zawierają pliki AssetBundle, kliknij Dodaj folder.

  2. W przypadku każdego pakietu zmień Tryb dostarczania na Czas instalacji, Szybkie śledzenie lub Na żądanie. Usuń błędy i zależności, a następnie zamknij okno.

  3. Aby utworzyć pakiet aplikacji, wybierz Google > Utwórz pakiet aplikacji na Androida.

  4. (Opcjonalnie) Skonfiguruj pakiet aplikacji tak, aby obsługiwał różne formaty kompresji tekstur.

Konfigurowanie pakietów zasobów za pomocą interfejsu API

Dostarczanie zasobów możesz skonfigurować za pomocą skryptów edytora, które można uruchamiać w ramach automatycznego systemu kompilacji.

Użyj klasy AssetPackConfig, aby określić, które zasoby mają zostać uwzględnione w kompilacji pakietu aplikacji na Androida, a także sposób ich dostarczania. Te pakiety komponentów nie muszą zawierać pliku 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);
}

Możesz też użyć statycznej metody BuildBundle w klasie Bundletool, aby wygenerować pakiet aplikacji na Androida z pakietami zasobów, pod warunkiem że użyjesz opcji BuildPlayerOptionsAssetPackConfig.

Przewodnik znajdziesz w ćwiczeniach z programowania Używanie Play Asset Delivery w grachach w Unity (wersja na komputer).

Integracja z interfejsem Play Asset Delivery API w Unity

Interfejs Play Asset Delivery API w Unity udostępnia funkcje umożliwiające żądanie pakietów zasobów, zarządzanie pobieraniem i dostęp do zasobów. Najpierw dodaj do projektu wtyczkę Unity.

Funkcje używane w interfejsie API zależą od sposobu utworzenia pakietów komponentów.

Jeśli pakiety komponentów zostały utworzone za pomocą interfejsu wtyczki, wybierz Pakiety komponentów skonfigurowane w pluginie.

Jeśli pakiety komponentów zostały utworzone za pomocą interfejsu API (lub interfejsu użytkownika w pluginie), wybierz pakiety komponentów skonfigurowane za pomocą interfejsu API.

Interfejs API jest wdrażany zgodnie z typem przesyłania pakietu zasobów, do którego chcesz uzyskać dostęp. Te kroki są pokazane na poniższym schemacie.

Schemat blokowy procesu pakietu komponentów dla wtyczki

Rysunek 1. Schemat procesu uzyskiwania dostępu do pakietów komponentów

Pobieranie AssetBundles

Zaimportuj bibliotekę komponentów do przesyłania zasobów Play i wywołaj metodę RetrieveAssetBundleAsync(), aby pobrać 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);

Przesyłanie podczas instalacji

Pakiety komponentów skonfigurowane jako install-time są dostępne od razu po uruchomieniu aplikacji. Aby załadować scenę z AssetBundle, wykonaj te czynności:

AssetBundle assetBundle = bundleRequest.AssetBundle;

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

Szybkie śledzenie i dostawy na żądanie

Te sekcje dotyczą pakietów komponentów fast-followon-demand.

Sprawdź stan

Każdy pakiet zasobów jest przechowywany w osobnym folderze w pamięci wewnętrznej aplikacji. Aby sprawdzić, czy pakiet zasobów został już pobrany, użyj metody isDownloaded().

Monitorowanie pobierania

Aby sprawdzić stan prośby, prześlij zapytanie do obiektu 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;
}

Pobieranie dużych plików

Pakiety zasobów większe niż 200 MB mogą być pobierane automatycznie, ale tylko przez Wi-Fi. Jeśli użytkownik nie jest połączony z siecią Wi-Fi, stan PlayAssetBundleRequest ma wartość AssetDeliveryStatus.WaitingForWifi, a pobieranie jest wstrzymane. W takim przypadku poczekaj, aż urządzenie połączy się z siecią Wi-Fi, a pobieranie zostanie wznowione, lub poproś użytkownika o pozwolenie na pobranie pakietu przez sieć komórkową.

Wymagane potwierdzenie użytkownika

Jeśli pakiet ma stan AssetDeliveryStatus.RequiresUserConfirmation, pobieranie nie rozpocznie się, dopóki użytkownik nie zaakceptuje wyświetlonego okna dialogowego z PlayAssetDelivery.ShowConfirmationDialog(). Ten stan może wystąpić, jeśli aplikacja nie jest rozpoznawana przez Google Play. Pamiętaj, że wywołanie funkcji PlayAssetDelivery.ShowConfirmationDialog() spowoduje zaktualizowanie aplikacji. Po aktualizacji ponownie poproś o zasoby.

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

Anulowanie prośby (tylko w przypadku wersji na żądanie)

Jeśli chcesz anulować żądanie przed załadowaniem AssetBundles do pamięci, wywołaj metodę AttemptCancel() obiektu PlayAssetBundleRequest:

// 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.
}

Prośba o pakiety komponentów w tle

W większości przypadków należy użyć routin, aby asynchronicznie żądać pakietów zasobów i monitorować postępy, jak pokazano poniżej:

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;

Więcej informacji o obsługiwaniu błędów znajdziesz na liście AssetDeliveryErrorCodes.

Inne metody interfejsu Play Core API

Oto kilka dodatkowych metod interfejsu API, których możesz używać w aplikacji.

Sprawdź rozmiar pobierania

Sprawdź rozmiar AssetBundle, wykonując asynchroniczne wywołanie Google Play i ustawiając metodę wywołania zwrotnego, która zostanie wywołana po zakończeniu operacji:

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

Usuwanie AssetBundles

Możesz usunąć AssetBundles na potrzeby szybkiego śledzenia i na żądanie, które nie są obecnie załadowane do pamięci. Wykonaj to asynchroniczne wywołanie i ustaw metodę wywołania zwrotnego, która zostanie wywołana po jego zakończeniu:

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.
                }
            };

Dalsze kroki

Testuj dostarczanie zasobów lokalnie i z Google Play.