{!See https://docs.google.com/document/d/1takg_GmIBBKKTj-GHZCwzxohpQz7Bhekivkk72kYMtE/edit for reference implementation of OneTrust, dataLayer and GTM} {!OneTrust Cookies Consent} {!OneTrust Cookies Consent end} {!dataLayer initialization push} {!dataLayer initialization push end} {!Google Tag Manager} {!Google Tag Manager end} 비동기 작업 핸들 | Addressables | 1.21.17
docs.unity3d.com
"{0}"의 검색 결과

    목차 표시/숨기기

    비동기 작업 핸들

    어드레서블의 많은 작업에서는 정보를 로드하거나 다운로드해야 결과를 반환할 수 있습니다. 프로그램 실행이 차단되지 않도록 어드레서블은 비동기 작업과 같은 작업을 구현합니다.

    동기 작업은 결과를 확인할 수 있을 때까지 컨트롤을 반환하지 않는 반면, 비동기 작업은 거의 즉각적으로 호출 메서드에 컨트롤을 반환합니다. 하지만 결과는 어느 정도 시간이 지나야 확인할 수 있습니다.

    LoadAssetAsync와 같은 메서드를 호출해도 로드된 에셋이 바로 반환되지 않습니다. 대신 AsyncOperationHandle 오브젝트를 반환하며, 이를 통해 로드된 에셋이 사용 가능해지면 해당 에셋에 액세스할 수 있습니다.

    다음과 같은 기술을 사용하여 다른 스크립트가 처리를 계속하도록 하면서 비동기 작업의 결과를 기다릴 수 있습니다.

    • 코루틴 및 IEnumerator 루프
    • 이벤트 기반 작업 처리
    • 태스크 기반 작업 처리

    [!참고] 현재 스레드를 차단하여 비동기 작업이 완료될 때까지 기다릴 수 있습니다. 이 경우 성능 문제가 발생하고 프레임 속도가 저하될 수 있습니다. 자세히 알아보려면 비동기식으로 작업 사용을 참조하십시오.

    AsyncOperationHandle 인스턴스 해제

    LoadAssetsAsync와 같은 메서드는 작업 결과와 결과 및 작업 오브젝트 자체를 해제하는 방법을 제공하는 AsyncOperationHandle 인스턴스를 반환합니다.

    결과를 사용하려는 기간에는 핸들 오브젝트를 유지해야 합니다. 상황에 따라 한 프레임이 될 수도 있고 하나의 레벨이 끝날 때까지일 수도 있으며, 애플리케이션의 수명 주기 내내일 수도 있습니다. 작업 핸들 및 관련 어드레서블 에셋을 해제하려면 Addressables.Release 메서드를 사용하십시오.

    작업 핸들을 해제하면 작업을 통해 로드된 모든 에셋의 레퍼런스 수가 감소하고 작업 핸들 오브젝트 자체가 무효화됩니다. 어드레서블 시스템의 레퍼런스 수에 대한 자세한 내용은 메모리 관리를 참조하십시오.

    제한된 범위 이외의 작업 결과를 사용할 필요가 없는 경우 핸들을 즉시 해제할 수 있습니다. UnloadSceneAsync와 같은 일부 어드레서블 메서드는 작업이 완료된 경우 자동으로 작업 핸들을 해제할 수 있게 합니다.

    작업이 실패한 경우에도 작업 핸들을 해제해야 합니다. 어드레서블은 실패한 작업 중에 로드한 모든 에셋을 해제하지만, 핸들을 해제해도 핸들의 인스턴스 데이터는 삭제됩니다. LoadAssetsAsync와 같이 여러 에셋을 로드하는 일부 메서드는 로드한 에셋을 유지하거나 로드 작업이 실패할 경우 모든 에셋을 실패 처리하고 해제할 수 있는 옵션을 제공합니다.

    코루틴 및 IEnumerator 작업 처리

    AsyncOperationHandle은 IEnumerator 인터페이스를 구현하며 작업이 완료될 때까지 반복 작업을 계속합니다.

    코루틴에서는 작업 핸들을 반환하여 다음 반복 작업을 기다릴 수 있습니다. 완료되면 실행 플로는 다음 문으로 이어집니다. MonoBehaviour Start 메서드를 코루틴으로 구현할 수 있으며, 이 경우 게임 오브젝트를 로드하고 필요한 에셋을 인스턴스화할 수 있습니다.

    다음 스크립트는 코루틴에서 Start 메서드를 사용하여 프리팹을 게임 오브젝트의 자식으로 로드합니다. 작업이 완료될 때까지 AsyncOperationHandle을 반환한 다음 동일한 핸들을 사용하여 프리팹을 인스턴스화합니다.

    
    using System.Collections;
    using UnityEngine;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;
    
    internal class LoadWithIEnumerator : MonoBehaviour
    {
        public string address;
        AsyncOperationHandle<GameObject> opHandle;
    
        public IEnumerator Start()
        {
            opHandle = Addressables.LoadAssetAsync<GameObject>(address);
    
            // yielding when already done still waits until the next frame
            // so don't yield if done.
            if (!opHandle.IsDone)
                yield return opHandle;
    
            if (opHandle.Status == AsyncOperationStatus.Succeeded)
            {
                Instantiate(opHandle.Result, transform);
            }
            else
            {
                Addressables.Release(opHandle);
            }
        }
    
        void OnDestroy()
        {
            Addressables.Release(opHandle);
        }
    }
    
    

    작업이 시작되면 Addressables.LoadAssetsAsync를 취소할 수 없습니다. 그러나 완료되기 전에 핸들을 해제하면 핸들 레퍼런스 수가 감소하며 로드가 완료되면 자동으로 핸들이 해제됩니다.

    자세한 내용은 Unity 사용자 매뉴얼의 코루틴 기술 자료를 참조하십시오.

    코루틴에서 작업 그룹화

    레벨을 시작하기 전에 프리팹 및 기타 에셋을 로드하는 등 게임 로직의 다음 단계로 넘어가기 전에 여러 작업을 수행하려면, 모든 작업이 에셋을 로드하는 경우 Addressables.LoadAssetsAsync 메서드에 대한 호출 한 번으로 작업을 결합할 수 있습니다.

    이 메서드에 대한 AsyncOperationHandle은 LoadAssetAsync와 동일하게 작동합니다. 코루틴에서 핸들을 반환하여 작업의 모든 에셋이 로드될 때까지 기다릴 수 있습니다. 또한 LoadAssetsAsync에 콜백 메서드를 전달할 수도 있으며, 특정 에셋의 로드가 완료되면 작업이 해당 메서드를 호출합니다. 여러 에셋 로드에서 예시를 확인해 보십시오.

    또한 ResourceManager.CreateGenericGroupOperation을 사용하여 모든 작업을 마치면 완료되는 그룹 작업을 만들 수 있습니다.

    이벤트 기반 작업 처리

    AsyncOperationHandle의 Completed 이벤트에 델리게이트 함수를 추가할 수 있습니다. 작업이 완료되면 델리게이트 함수가 호출됩니다.

    다음 스크립트는 코루틴 및 IEnumerator 작업 처리의 예시와 등일한 기능을 수행하지만 코루틴 대신 이벤트 델리게이트를 사용합니다.

    
    using UnityEngine;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;
    
    internal class LoadWithEvent : MonoBehaviour
    {
        public string address;
        AsyncOperationHandle<GameObject> opHandle;
    
        void Start()
        {
            // Create operation
            opHandle = Addressables.LoadAssetAsync<GameObject>(address);
            // Add event handler
            opHandle.Completed += Operation_Completed;
        }
    
        private void Operation_Completed(AsyncOperationHandle<GameObject> obj)
        {
            if (obj.Status == AsyncOperationStatus.Succeeded)
            {
                Instantiate(obj.Result, transform);
            }
            else
            {
                Addressables.Release(obj);
            }
        }
    
        void OnDestroy()
        {
            Addressables.Release(opHandle);
        }
    }
    
    

    이벤트 델리게이트에 전달된 핸들 인스턴스는 원래 메서드 호출에서 반환된 것과 동일합니다. 둘 중 하나를 사용하여 작업의 결과 및 상태에 액세스하고 작업 핸들 및 로드된 에셋을 해제할 수 있습니다.

    태스크 기반 작업 처리

    AsyncOperationHandle은 비동기 메서드를 호출하고 결과를 처리하는 코드를 배열하기 위해 C# async 및 await 키워드와 함께 사용할 수 있는 Task 오브젝트를 제공합니다.

    다음 예시에서는 키 목록을 사용하여 어드레서블 에셋을 로드합니다. 태스크 기반 접근 방식과 코루틴 또는 이벤트 기반 접근 방식의 차이는 호출 메서드의 서명에 있습니다. 이 메서드에는 async 키워드가 포함되어야 하며, 작업 핸들의 Task 프로퍼티와 함께 await 키워드를 사용해야 합니다. 이 경우 호출 메서드인 Start는 태스크가 완료되는 동안 작업을 일시 중지합니다. 그런 다음 실행이 재개되며, 예시에서는 로드된 모든 프리팹을 그리드 패턴으로 인스턴스화합니다.

    
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;
    
    internal class LoadWithTask : MonoBehaviour
    {
        // Label or address strings to load
        public List<string> keys = new List<string>() {"characters", "animals"};
    
        // Operation handle used to load and release assets
        AsyncOperationHandle<IList<GameObject>> loadHandle;
    
        public async void Start()
        {
            loadHandle = Addressables.LoadAssetsAsync<GameObject>(
                keys, // Either a single key or a List of keys 
                addressable =>
                {
                    // Called for every loaded asset
                    Debug.Log(addressable.name);
                }, Addressables.MergeMode.Union, // How to combine multiple labels 
                false); // Whether to fail if any asset fails to load
    
            // Wait for the operation to finish in the background
            await loadHandle.Task;
    
            // Instantiate the results
            float x = 0, z = 0;
            foreach (var addressable in loadHandle.Result)
            {
                if (addressable != null)
                {
                    Instantiate<GameObject>(addressable,
                        new Vector3(x++ * 2.0f, 0, z * 2.0f),
                        Quaternion.identity,
                        transform); // make child of this object
    
                    if (x > 9)
                    {
                        x = 0;
                        z++;
                    }
                }
            }
        }
    
        private void OnDestroy()
        {
            Addressables.Release(loadHandle);
            // Release all the loaded assets associated with loadHandle
            // Note that if you do not make loaded addressables a child of this object,
            // then you will need to devise another way of releasing the handle when
            // all the individual addressables are destroyed.
        }
    }
    
    

    [!중요] AsyncOperationHandle.Task 프로퍼티는 멀티태스킹을 지원하지 않는 WebGL 플랫폼에서 사용이 불가합니다.

    Task 기반 작업 처리를 사용할 경우 WhenAll과 같은 C# Task 클래스 메서드를 사용하여 병렬로 실행할 작업과 순서대로 실행할 작업을 제어할 수 있습니다. 다음 예시에서는 다음 태스크로 넘어가기 전에 두 개 이상의 작업이 완료되기를 기다리는 방법을 보여 줍니다.

    
    // Load the Prefabs
    var prefabOpHandle = Addressables.LoadAssetsAsync<GameObject>(
        keys, null, Addressables.MergeMode.Union, false);
    
    // Load a Scene additively
    var sceneOpHandle
        = Addressables.LoadSceneAsync(nextScene,
            UnityEngine.SceneManagement.LoadSceneMode.Additive);
    
    await System.Threading.Tasks.Task.WhenAll(prefabOpHandle.Task, sceneOpHandle.Task);
    
    

    비동기식으로 작업 사용

    반환하거나, 이벤트를 기다리거나, 작업의 WaitForCompletion 메서드를 호출하여 async await를 사용하지 않고 작업이 완료되기를 기다릴 수 있습니다. 이 메서드는 기존의 프로그램 실행 스레드가 현재 범위에서 계속하기 전에 작업이 완료되기를 기다리는 동안 해당 스레드를 차단합니다.

    데이터를 다운로드해야 하는 작업과 같이 상당한 시간이 소요될 수 있는 작업에서는 WaitForCompletion을 호출하지 마십시오. WaitForCompletion을 호출하면 프레임에 문제가 발생하고 UI 응답성이 저하될 수 있습니다.

    다음 예시에서는 주소별로 프리팹 에셋을 로드하고 작업이 완료될 때까지 기다린 다음 프리팹을 인스턴스화합니다.

    
    using UnityEngine;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;
    
    internal class LoadSynchronously : MonoBehaviour
    {
        public string address;
        AsyncOperationHandle<GameObject> opHandle;
    
        void Start()
        {
            opHandle = Addressables.LoadAssetAsync<GameObject>(address);
            opHandle.WaitForCompletion(); // Returns when operation is complete
    
            if (opHandle.Status == AsyncOperationStatus.Succeeded)
            {
                Instantiate(opHandle.Result, transform);
            }
            else
            {
                Addressables.Release(opHandle);
            }
        }
    
        void OnDestroy()
        {
            Addressables.Release(opHandle);
        }
    }
    
    

    커스텀 작업

    커스텀 작업을 생성하려면 AsyncOperationBase 클래스를 확장한 다음 가상 메서드를 오버라이드합니다.

    파생된 작업을 ResourceManager.StartOperation 메서드에 전달하여 작업을 시작하고 AsyncOperationHandle 구조체를 수신할 수 있습니다. ResourceManager는 이렇게 시작된 작업을 등록합니다.

    커스텀 작업 실행

    선택적 종속 작업이 완료되면 ResourceManager가 커스텀 작업을 위해 AsyncOperationBase.Execute 메서드를 호출합니다.

    완료 처리

    커스텀 작업이 완료되면 커스텀 작업 오브젝트에서 AsyncOperationBase.Complete를 호출합니다. Execute 메서드에서 호출하거나 호출 외부로 지연시킬 수 있습니다. AsyncOperationBase.Complete가 작업이 완료되었음을 ResourceManager에 알립니다. ResourceManager는 커스텀 작업의 관련 인스턴스에 대한 AsyncOperationHandle.Completed 이벤트를 호출합니다.

    커스텀 작업 종료

    AsyncOperationBase.ReferenceCount 작업이 0에 도달하면 ResourceManager가 커스텀 작업을 위해 AsyncOperationBase.Destroy 메서드를 호출합니다. AsyncOperationBase.ReferenceCount는 이를 참조하는 AsyncOperationHandle이 Addressables.Release를 사용하여 해제되거나 AsyncOperationBase.DecrementReferenceCount가 내부에서 커스텀 작업에 의해 호출될 때 감소합니다. AsyncOperationBase.Destroy에서 커스텀 작업과 관련된 메모리나 리소스를 해제해야 합니다.

    입력 및 무입력 작업 핸들

    작업을 시작하는 대부분의 Addressables 메서드는 일반 AsyncOperationHandle<T> 구조체를 반환하여 AsyncOperationHandle.Completed 이벤트 및 AsyncOperationHandle.Result 오브젝트에 대한 입력 안전성을 제공합니다. 또한 비일반 AsyncOperationHandle 구조체를 사용하고 두 개의 핸들 유형을 원하는 대로 전환할 수 있습니다.

    비일반 핸들을 잘못된 유형의 일반 핸들로 캐스트하려고 하면 런타임 예외가 발생합니다. 예제:

    
    // Load asset using typed handle:
    AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
    
    // Convert the AsyncOperationHandle<Texture2D> to an AsyncOperationHandle:
    AsyncOperationHandle nonGenericHandle = textureHandle;
    
    // Convert the AsyncOperationHandle to an AsyncOperationHandle<Texture2D>:
    AsyncOperationHandle<Texture2D> textureHandle2 = nonGenericHandle.Convert<Texture2D>();
    
    // This will throw and exception because Texture2D is required:
    AsyncOperationHandle<Texture> textureHandle3 = nonGenericHandle.Convert<Texture>();
    
    

    보고서 작업 진행

    AsyncOperationHandle에서는 다음 메서드를 사용하여 작업 진행 상황을 모니터링하고 보고할 수 있습니다.

    • GetDownloadStatus: DownloadStatus 구조체를 반환합니다. 이 구조체에는 다운로드된 바이트 수와 아직 다운로드해야 하는 바이트 수에 대한 정보가 포함되어 있습니다. DownloadStatus.Percent에서 다운로드된 바이트의 백분율을 보고합니다.
    • AsyncOperationHandle.PercentComplete: 완료된 모든 하위 작업에 대해 동일한 가중치가 적용된 총 백분율을 반환합니다. 예를 들어 하나의 작업에 5개의 하위 작업이 있는 경우 각 하위 작업은 전체의 20%를 차지합니다. 개별 하위 작업에서 다운로드해야 하는 데이터의 양은 이 값에 영향을 미치지 않습니다.

    예를 들어 Addressables.DownloadDependenciesAsync를 호출하고 5개의 에셋 번들을 다운로드해야 하는 경우, GetDownloadStatus는 모든 하위 작업의 총 바이트 수 대비 다운로드된 바이트 수의 백분율을 알려 줍니다. PercentComplete는 작업의 크기에 관계 없이 완료된 작업 수의 백분율을 알려 줍니다.

    LoadAssetAsync를 호출했으며 하나의 번들을 다운로드해야 에셋을 로드할 수 있는 경우, 정확한 다운로드 백분율을 구하기 어려울 수 있습니다. 수행해야 할 추가 하위 작업이 있으므로 GetDownloadStatus에서 얻은 값은 작업이 완료되기 전에 100%에 도달합니다. PercentComplete의 값은 다운로드 하위 작업이 완료되면 50%, 실제 메모리 로드가 완료되면 100%가 됩니다.

    문서 개요
    맨 위로
    Copyright © 2023 Unity Technologies — 상표 및 이용약관
    • 법률정보
    • 개인정보처리방침
    • 쿠키
    • 내 개인정보 판매 금지
    • Your Privacy Choices (Cookie Settings)