Integrar a entrega de recursos (Unity)

Ao integrar a entrega de recursos, os jogos do Unity podem acessar pacotes de recursos usando Addressables ou AssetBundles. Os Addressables são a solução de entrega de recursos mais recente e recomendada para jogos criados com Unity 2019.4 ou mais recente, enquanto os AssetBundles dão suporte a pacotes de recursos no Unity 2017.4 e 2018.4.

Addressables do Unity

Jogos criados com Unity 2019.4 ou versões mais recentes precisam usar Addressables (link em inglês) para a entrega de recursos no Android. O Unity oferece a API Play Asset Delivery (PAD) para processar pacotes de recursos do Android usando Addressables. Para saber informações sobre como usar Addressables, consulte o estes links (em inglês):

Usar arquivos AssetBundle

Os jogos criados com Unity 2017.4 e 2018.4 podem usar arquivos AssetBundle para entrega de recursos no Android. Os arquivos AssetBundle (link em inglês) do Unity contêm recursos serializados que podem ser carregados pelo mecanismo do Unity enquanto o app está em execução. Esses arquivos são específicos da plataforma (por exemplo, criados para Android) e podem ser usados em combinação com pacotes de recursos. Geralmente, um arquivo AssetBundle é combinado em um único pacote que usa o mesmo nome do AssetBundle. Se você quiser mais flexibilidade na criação de um pacote de recursos, configure-o usando a API.

No ambiente de execução, use a classe Play Asset Delivery para Unity para extrair um AssetBundle empacotado em um pacote de recursos.

Pré-requisitos

  1. Configure o ambiente de desenvolvimento:

OpenUPM-CLI

Se você tiver a CLI do OpenUPM instalada, poderá instalar o registro do OpenUPM com o seguinte comando:

openupm add com.google.play.assetdelivery

OpenUPM

  1. Abra as configurações do gerenciador de pacotes selecionando a opção de menu do Unity Edit > Project Settings > Package Manager.

  2. Adicione o OpenUPM como um registro de escopo à janela do Gerenciador de pacotes:

    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. Abra o menu do gerenciador de pacotes selecionando a opção de menu do Unity Window > Package Manager.

  4. Defina o menu suspenso "Escopo do administrador" para selecionar Meus registros.

  5. Selecione o pacote Google Play Integrity plugin for Unity na lista de pacotes e pressione Install.

Importar do GitHub

  1. Faça o download da versão mais recente do .unitypackage no GitHub.

  2. Importe o arquivo .unitypackage selecionando a opção de menu do Unity Assets > Import package > Custom Package e importando todos os itens.

  1. Crie AssetBundles no Unity.

Configurar AssetBundles usando a interface

  1. Configure cada AssetBundle em um pacote de recursos:

    1. Selecione Google > Android App Bundle > Asset Delivery Settings.
    2. Para selecionar pastas que contenham arquivos do AssetBundle diretamente, clique em Add Folder.

  2. Para cada pacote, mude o Delivery Mode para Install Time, Fast Follow ou On demand. Resolva erros ou dependências e feche a janela.

  3. Selecione Google > Build Android App Bundle para criar o pacote de apps.

  4. (Opcional) Configure seu pacote de apps para que ele seja compatível com diferentes formatos de compactação de textura.

Configurar pacotes de recursos usando a API

Você pode configurar a entrega de recursos pelos scripts de editor, que podem ser executados como parte de um sistema de compilação automatizado.

Use a classe AssetPackConfig para definir quais recursos incluir em uma compilação do Android App Bundle, bem como o modo de entrega dos recursos. Esses pacotes de recursos não precisam conter um 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);
}

Você também pode usar o método estático BuildBundle na classe Bundletool para gerar um Android App Bundle com pacotes de recursos, usando BuildPlayerOptions (link em inglês) e AssetPackConfig.

Observação: para conferir um tutorial guiado, consulte o codelab Como usar a Play Asset Delivery em jogos do Unity.

Integrar com a API Play Asset Delivery Unity

A API Unity Play Asset Delivery oferece a funcionalidade de solicitar pacotes de recursos, gerenciar downloads e acessar os recursos. Primeiro, adicione o plug-in do Unity ao projeto.

As funções usadas na API dependem de como você criou os pacotes de recursos.

Se você criou pacotes de recursos usando a IU do plug-in, selecione Pacotes de recursos configurados pelo plug-in.

Se você criou pacotes de recursos usando a API (ou a interface do plug-in), selecione Pacotes de recursos configurados pela API.

A API é semelhante, independentemente do tipo de entrega do pacote de recursos que você quer acessar. Essas etapas são mostradas no fluxograma a seguir.

Diagrama de fluxo de pacotes de recursos para a API

Figura 1. Diagrama de fluxo para acessar pacotes de recursos

Recuperar um pacote de recursos

Importe a biblioteca Play Asset Delivery e chame o método RetrieveAssetPackAsync() para fazer o download de um pacote de recursos se a versão mais recente do pacote ainda não estiver disponível no disco.

using Google.Play.AssetDelivery;

// After download, the assets and/or AssetBundles contained in the asset pack
// are not loaded into memory.
PlayAssetPackRequest request = PlayAssetDelivery.RetrieveAssetPackAsync(assetPackName);

Entrega na instalação

Um pacote de recursos configurado como install-time fica imediatamente disponível na inicialização do app, mas você precisa carregar os recursos na memória. Consulte Carregar recursos na memória.

Entrega rápida e sob demanda

Essas seções se aplicam aos pacotes de recursos fast-follow e on-demand.

Verificar status

Cada pacote de recursos é armazenado em uma pasta separada no armazenamento interno do app. Use o método isDone() para determinar se um pacote de recursos já foi transferido por download e está disponível, ou se ocorreu um erro.

Monitorar o download

Consulte o objeto PlayAssetPackRequest para monitorar o status da solicitação:

// 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 does not mean that the request has completed, only that
// the DOWNLOADING stage is finished.
float progress = request.DownloadProgress;

// Returns the status of the retrieval request.
// If the request completed successfully, this value should be AssetDeliveryStatus.Available.
// If an error occurred, this value should be AssetDeliveryStatus.Failed.

AssetDelivery status = request.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.Failed:
        // Asset pack retrieval 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;
}

// Returns true if status is AssetDeliveryStatus.Available or AssetDeliveryStatus.Failed.
bool done = request.IsDone;

// If AssetDeliveryStatus.Failed, find more info about the error.
AssetDeliveryErrorCode error = request.Error;

Downloads grandes

Os pacotes de recursos com mais de 200 MB podem ser transferidos por download automaticamente, mas somente se o dispositivo estiver conectado a uma rede Wi-Fi. Se o usuário não estiver usando Wi-Fi, o status PlayAssetPackRequest será definido como AssetDeliveryStatus.WaitingForWifi e o download será pausado. Nesse caso, aguarde até que o dispositivo se conecte à rede Wi-Fi, retome o download ou peça ao usuário aprovação para fazer o download do pacote em uma conexão celular.

Confirmação do usuário necessária

Se um pacote tiver o status AssetDeliveryStatus.RequiresUserConfirmation, o download não vai prosseguir até que o usuário aceite a caixa de diálogo mostrada com PlayAssetDelivery.ShowConfirmationDialog(). Esse status pode surgir se o app não for reconhecido pelo Google Play. Chamar PlayAssetDelivery.ShowConfirmationDialog() nesse caso faz com que o app seja atualizado. Após a atualização, solicite os recursos novamente.

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

Cancelar uma solicitação (somente sob demanda)

Se você precisar cancelar a solicitação antes do download dos pacotes de recursos ser concluído, chame o método AttemptCancel() no objeto PlayAssetPackRequest:

// Will only attempt if the status is Pending, Retrieving, or Available; otherwise
// it will be a no-op.
request.AttemptCancel();

// Check to see if the request was successful by checking if the error code is Canceled.
if(request.Error == AssetDeliveryErrorCode.Canceled) {
    // Request was successfully canceled.
}

Carregar recursos na memória

Quando a solicitação for concluída, use uma destas funções para carregar recursos na memória:

Solicitar pacotes de recursos de forma assíncrona

Na maioria dos casos, é preciso usar Corrotinas para solicitar pacotes de recursos de forma assíncrona e monitorar o progresso, como mostrado a seguir:

private IEnumerator LoadAssetPackCoroutine(string assetPackName) {

    PlayAssetPackRequest request =
        PlayAssetDelivery.RetrieveAssetPackAsync(assetPackName);

    while (!request.IsDone) {
        if(request.Status == AssetDeliveryStatus.WaitingForWifi) {
            var userConfirmationOperation = PlayAssetDelivery.ShowConfirmationDialog();

            // 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(() => request.Status != AssetDeliveryStatus.WaitingForWifi);
        }

        // Use request.DownloadProgress to track download progress.
        // Use request.Status to track the status of request.

        yield return null;
    }

    if (request.Error != AssetDeliveryErrorCode.NoError) {
        // There was an error retrieving the pack. 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. Load the asset pack into memory.
    AssetBundleCreateRequest assetBundleCreateRequest = request.LoadAssetBundleAsync(path/to/exampleBundle);
    yield return assetBundleCreateRequest;
    AssetBundle assetBundle = assetBundleCreateRequest.assetBundle;

Para ver mais informações sobre como lidar com erros, consulte a lista de códigos de erro.

Outros métodos da API Play Core

Veja a seguir alguns métodos adicionais de API que podem ser usados no seu app.

Recuperar vários pacotes de recursos

Para recuperar vários pacotes de recursos de uma só vez, use a seguinte função:

// assetPackNames is an array of strings corresponding to asset packs.
PlayAssetPackBatchRequest batchRequest = PlayAssetDelivery.RetrieveAssetPackBatchAsync(<IListstring> assetPackNames);

Monitore os status de cada solicitação inspecionando o Dictionary de estados:

// Dictionary of AssetPackStates, with the asset pack name as the key.
Dictionary<string, PlayAssetPackRequest> requests = batchRequest.Requests;

// Returns true if all requests are complete.
bool requestComplete = batchRequest.IsDone;

Verificar o tamanho do download

Verifique o tamanho de um pacote de recursos fazendo uma chamada assíncrona ao Google Play e definindo um método de callback para quando a operação for concluída:

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

Remover AssetBundles

É possível remover pacotes de recursos rápidos e sob demanda que não estão carregados na memória no momento. Faça a chamada assíncrona a seguir e defina um método de callback para conclusão:

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

Próximas etapas

Teste a entrega de recursos localmente e no Google Play.