Asset Delivery 통합(Unity)

Asset Delivery를 통합할 때 Unity 게임은 Addressables 또는 AssetBundle을 사용하여 애셋 팩에 액세스할 수 있습니다. Addressables는 Unity 2019.4 및 이후 버전으로 빌드된 게임을 위한 최신 권장 애셋 제공 솔루션인 반면, AssetBundle은 Unity 2017.4 및 2018.4의 애셋 팩을 지원합니다.

Unity Addressable

Unity 2019.4 및 이후 버전으로 빌드된 게임은 Android에서 에셋 제공용으로 Addressables를 사용해야 합니다. Unity는 Addressables를 사용한 Android 애셋 팩을 처리하기 위한 Play Asset Delivery(PAD) API를 제공합니다. Addressables 사용에 관한 자세한 내용은 다음을 참고하세요.

AssetBundle 파일 사용

Unity 2017.4 및 2018.4로 빌드된 게임은 Android에서 애셋 제공에 AssetBundle 파일을 사용할 수 있습니다. Unity AssetBundle 파일에는 앱이 실행되는 동안 Unity 엔진에서 로드할 수 있는 직렬화된 애셋이 포함되어 있습니다. 이러한 파일은 플랫폼에 따라 다르며(예: Android용으로 빌드) 애셋 팩과 함께 사용할 수 있습니다. 가장 흔하게 하나의 AssetBundle 파일은 단일 애셋 팩으로 패키징되며, 팩은 AssetBundle과 동일한 이름을 사용합니다. 애셋 팩을 더 유연하게 생성하려면 API를 사용하여 애셋 팩을 구성해야 합니다.

런타임 시 Unity용 Play Asset Delivery 클래스를 사용하여 애셋 팩에 패키징된 AssetBundle을 검색합니다.

기본 요건

  1. Unity용 Google 패키지에서 Play Asset Delivery Unity 플러그인의 최신 버전을 다운로드합니다.

  2. Unity에서 AssetBundle을 생성합니다.

UI를 사용하여 AssetBundle 구성

  1. 다음과 같이 애셋 팩에서 각 AssetBundle을 구성합니다.

    1. Google > Android App Bundle > Asset Delivery Settings를 선택합니다.
    2. AssetBundle 파일이 직접 포함된 폴더를 선택하려면 Add Folder를 클릭합니다.

  2. 각 번들에 대해 Delivery ModeInstall Time, Fast Follow 또는 On Demand로 변경합니다. 오류 또는 종속 항목을 해결하고 창을 닫습니다.

  3. Google > Build Android App Bundle을 선택하여 App Bundle을 빌드합니다.

  4. (선택사항) 다양한 텍스처 압축 형식을 지원하도록 App Bundle을 구성합니다.

API를 사용하여 애셋 팩 구성

자동화된 빌드 시스템의 일부로 실행할 수 있는 편집기 스크립트를 통해 Asset Delivery를 구성할 수 있습니다.

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 메서드를 사용하여 BuildPlayerOptionsAssetPackConfig가 지정된 애셋 팩이 있는 Android App Bundle을 생성할 수도 있습니다.

자세한 가이드는 Unity 게임에서 Play Asset Delivery 사용 Codelab을 참고하세요.

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

대용량 다운로드

200MB보다 큰 애셋 팩은 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 메서드입니다.

다운로드 크기 확인

다음과 같이 비동기 Google Play 호출을 실행하고 작업 완료 시의 콜백 메서드를 설정하여 AssetBundle 크기를 확인합니다.

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를 테스트합니다.