본문 바로가기
프로그래밍/Unity

Unity - Addressable Patch Download

by neive 2022. 10. 11.
728x90

 

대략 이렇게 어드레서블 세팅이 된게 있다고 치고 자연스럽게 전체적으로 패치를 받는걸 찾는데 영 시원한 예제를 찾을 수 없던 중...

https://github.com/Wenrong274/Unity-Addressable

 

GitHub - Wenrong274/Unity-Addressable: 主要是實作 Addressable hotfix 的寫法。

主要是實作 Addressable hotfix 的寫法。. Contribute to Wenrong274/Unity-Addressable development by creating an account on GitHub.

github.com

중국 형님의 글 발견.. 역시 대세는 중국 프로그래머인가

 

아무튼 잘 참고하여 아래처럼 정리...

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class Launcher : MonoBehaviour
{
    [SerializeField] private Button button_patch;
    [SerializeField] private Button button_enter;
    [SerializeField] private Button button_clean;
    [SerializeField] private GameObject item_log;
    [SerializeField] private Transform root_log;
    [SerializeField] private Image image_progress;
    [SerializeField] private Text text_progress;
    
    private long patchSize;
    private Dictionary<string, long> progress = new Dictionary<string, long>();

    private void Awake()
    {
        button_patch.onClick.AddListener(OnPatch);
        button_enter.onClick.AddListener(GoLobby);
        button_clean.onClick.AddListener(ClearCache);
    }




    private void OnPatch()
    {
        StartCoroutine(Patch());
    }

    private IEnumerator CheckUpdate(List<string> labels)
    {
        patchSize = default;

		// 이렇게 select 로 하면 pc 환경에서는 잘 동작하는데 안드로이드 환경에서 size 가 0
        /*
        foreach (var handle in labels.Select(Addressables.GetDownloadSizeAsync))
        {
            yield return handle;

            m_PatchSize += handle.Result;
        }
        */
        
        foreach (var label in labels)
        {
            var handle = Addressables.GetDownloadSizeAsync(label);

            yield return handle;
            
            patchSize += handle.Result;
        }
    }
    
    private IEnumerator Patch()
    {
        var labels = new List<string>() { "Effect", "Character", "Scene", "Atlas" };
        
        yield return CheckUpdate(labels);

        if (patchSize > decimal.Zero)
        {
            foreach (var label in labels)
            {
                var handle = Addressables.GetDownloadSizeAsync(label);

                yield return handle;

                if (handle.Result != decimal.Zero)
                    StartCoroutine(Download(label));
            }
            
            yield return CheckDownload();
        }
        else
        {
            image_progress.fillAmount = 1.0f;
        	text_progress.text = "100%";
        }
    }
    
    IEnumerator Download(string label)
    {
        progress.Add(label, 0);
        
        var handle = Addressables.DownloadDependenciesAsync(label, false);

        while (!handle.IsDone)
        {
            progress[label] = handle.GetDownloadStatus().DownloadedBytes;
            yield return new WaitForEndOfFrame();
        }

        progress[label] = handle.GetDownloadStatus().TotalBytes;
        
        Addressables.Release(handle);
    }

    IEnumerator CheckDownload()
    {
        var total = 0.0f;
        image_progress.fillAmount = 0.0f;
        text_progress.text = "0%";
        
        while (true)
        {
            total += progress.Sum(tmp => tmp.Value);
            image_progress.fillAmount = total / patchSize;
            text_progress.text = $"{(int)(image_progress.fillAmount * 100)}%";

            if (total == patchSize)
                break;

            total = 0.0f;
            yield return new WaitForEndOfFrame();
        }
    }
    
    private void GoLobby()
    {
        SceneManager.LoadScene("Lobby");
    }
    
    private void ClearCache()
    {
        StartCoroutine(ClearCache_());
    }

    private IEnumerator ClearCache_()
    {
        foreach (var tmp in Addressables.ResourceLocators)
        {
            var async = Addressables.ClearDependencyCacheAsync(tmp.Keys, false);
            yield return async;
            Addressables.Release(async);
        }

        Caching.ClearCache();
        Addressables.UpdateCatalogs();
    }
}

참 쉬운데 이거 찾기가 이리 어려워 직접 만들게 되는구만...

나중에는 저 라벨 넣는 부분을 카탈로그 같은 것을 이용해서 자동으로 구성되게 하는게 아마 최종 업그레이드

 

 

 

https://youtu.be/J5G_ByeBsiQ

패치 다운 받고 불러보기

 

https://youtu.be/oR9tVhl04wQ

 

 

씬 어드레서블 빌드 할 때 최초 다운로드 (Launcher 씬이라고 치자) 

씬만 제외 하고 나머지는 체크에서 꺼야 한다.. 그렇게 하지 많으면

apk 에 씬이 포함되어버리고 이미 가지고 있는 리소스라 번들이 카

달로그에 포함되지 않는다

 

 

에디터에서 쉐이더가 핑크로 나온다면?

https://sunpil.tistory.com/506

 

Addressable 사용 시 Shader가 깨질 때(분홍색으로 나옴)

Problem Reason Addresssable의 Shader는 Android용으로 Pack되어서 Editor에서 안열리는 것 Solution Android에서는 잘 보이고, Editor에서 테스트 시에만 잘 안보이는 것. Reference http://cargocollective.com/mingruijiang/Shaders-

sunpil.tistory.com

 

위까지는 최초 패치 버전이고 이후 패치는

 

프리팹을 수정하고 Addressables Groups 에서

 

Build -> Update a Previous Build 를 선택 후

 

빌드하려는 플랫폼 폴더로 들어가서 (ex Android)

 

bin 파일을 선택하면 패치 빌드가 되면서 새로 

 

생긴 파일들만 cdn 에 업로드 하면 되겠다 

 

 

기타 유용한 자료

 

https://uwostudy.tistory.com/76

 

Addressable Assets development cycle (3)

어드레서블에 대한 이해를 하고자 해보았으나 실제 사용하는 방법은 약간 차이가 있다. 일단 하던 번역은 마무리하고 실제 사용 전략에 대해 정리할 예정이다. 2020/06/09 - [개발/Unity] - Addressable As

uwostudy.tistory.com

 

728x90

댓글