Unity之Addressable使用注意事项

Posted 天涯过客TYGK

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity之Addressable使用注意事项相关的知识,希望对你有一定的参考价值。

基本设置

Profile文件中配置资源构建路径和资源首次加载路径,资源如何设置了缓存,在首次加载之后会将再用缓存在缓存目录,后面将直接从缓存目录中读取,RemoteLoadPath一般要设置成可以动态修改类型的参数,方便项目发包时候进行使用

AddressableAssetSettings文件
DisableCatalogUpdateOnStartup 勾选改选项,禁止自动更新,项目资源下载一般需要提示玩家下载资源大小和下载进度,需要通过代码进行手动下载更新
BuildRemoteCatalog 创建远端资源的catalog,用于热更新资源
设置BuildPath和 LoadPath
根据自身网络状况设置资源最大的请求数和下载超时时间

Group文件注意设置BundleMode ,是否将group内的资源分散打包

Remote资源缓存

unity自身默认缓存路径是 C:\\Users\\admin\\AppData\\LocalLow\\Unity
Addressable默认缓存路径 C:\\Users\\admin\\AppData\\LocalLow\\Unity\\项目名称_AdressableLoad
可以指定远端远端资源在本地缓存路径,需要注意的是,如果项目刚开始运行的时候没有手动设置缓存目录,在手动添加缓存目录之后默认缓存目录中已经存在的资源并不会被释放,每次加载读取的时候,先从手动设置的缓存目录中查找,在从默认缓存中查找,如果默认缓存中存在资源,则不会重新进行下载
创建CacheInitializationSettings文件,然后将改文件关联到AddressableAssetSettings的inititalizationObjects中,方法如下

手动设置缓存路径(如下图所示方式会缓存在工程根目录的AAAAAAA文件夹内,也可设置为 persistentDataPath 格式为UnityEngine.Application.persistentDataPath)


每一个下载下来的bundle资源,会被缓存为_data 和_info两个文件,(猜测:_info是索引文件信息,_data是资源序列化内容)

代码部分

资源下载检测

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AddressableManager : MonoBehaviour

    public static AddressableManager instance;
    List<object> keys;//addressable ×ÊÔ´µÄlabel¼¯ºÏ£¬Ò»°ãͬһÀàÐ͵Ä×ÊÔ´ÓÃÒ»¸ölabel
    AsyncOperationStatus checkStatus;
    long totalDownloadSize = 0;
    public event Action<AsyncOperationStatus> onCheckFinish;

    // Start is called before the first frame update
    private void Awake()
    
        instance = this;
        DontDestroyOnLoad(this.gameObject);
    
    

    public IEnumerator CheckUpadate()
    
        keys = new List<object>();
        totalDownloadSize = 0;
        yield return Addressables.InitializeAsync();
        Debug.Log("初始化检测更新");
        var checkHandle = Addressables.CheckForCatalogUpdates(false);//false是手动释放异步结果对象
        yield return checkHandle;
        Debug.Log("catalogs chek res:" + checkHandle.Status);
        if(checkHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
        
            List<string> catalogs = checkHandle.Result;
           
            if(catalogs != null && catalogs.Count > 0)
            
                var updateHandle = Addressables.UpdateCatalogs(catalogs, false);
                yield return updateHandle;

                var catlogResult = updateHandle.Result;
                int idx = 0;
                foreach (var item in catlogResult)
                
                    // var itemKeys = new List<object>  item.Keys ;
                    // for (int i = 0; i < itemKeys.Count; i++)
                    // 
                    //     Debug.Log($"index:idx,key:itemKeys[i]");
                    // 
                    foreach (var key in item.Keys)
                    
                        if (key is string)
                        
                            // if (!itemKeys.Any(x => x == key.ToString()))
                                keys.Add(key.ToString());
                        
                    
                    
                
                // keys = new List<object>  catlogResult[0].Keys ;
                Debug.Log("updatehandle res:" + updateHandle.Status);
                Debug.Log("updatehandle res:" + keys[0].ToString());
                if (updateHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
                
                    var sizeHandle = Addressables.GetDownloadSizeAsync(keys);
                    yield return sizeHandle;
                    if(sizeHandle.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
                    
                        totalDownloadSize = sizeHandle.Result;
                        Debug.Log("下载资源大小" + (totalDownloadSize / 1024.0f / 1024.0f).ToString("0.00"));
                        checkStatus = AsyncOperationStatus.Succeeded;
                        CheckForUpdate(); 
                    
                    else
                    
                        checkStatus = AsyncOperationStatus.Failed;
                        CheckForUpdate();
                    
                    Addressables.Release(sizeHandle);
                
                else
                
                    Debug.Log("¼ì²â¸üÐÂʧ°Ü£¬Çë¼ì²éÍøÂç×´¿ö");
                    checkStatus = AsyncOperationStatus.Failed;
                    CheckForUpdate();
                
                Addressables.Release(updateHandle);

            
            else
            
                Debug.Log("不需要更新catlog");
                keys.Add("HD");
                keys.Add("Movie");
                var sizeHandel = Addressables.GetDownloadSizeAsync(keys);
                yield return sizeHandel;
                if(sizeHandel.Status == AsyncOperationStatus.Succeeded)
                
                    totalDownloadSize = sizeHandel.Result;
                    Debug.Log("下载资源大小" + (totalDownloadSize / 1024.0f / 1024.0f).ToString("0.00"));
                    checkStatus = AsyncOperationStatus.Succeeded;
                    CheckForUpdate();
                
                else
                
                    Debug.Log("资源大小获取失败");
                    checkStatus = AsyncOperationStatus.Failed;
                    CheckForUpdate();
                
                Addressables.Release(sizeHandel);
            
        

    

     void CheckForUpdate()
    
        if(checkStatus == AsyncOperationStatus.Succeeded && totalDownloadSize > 0)
        
            StartCoroutine(ExcuteUpdate());
        else onCheckFinish?.Invoke(checkStatus);
    

    IEnumerator ExcuteUpdate()
    
        var downloadDependenciesHandle = Addressables.DownloadDependenciesAsync(keys, Addressables.MergeMode.Union, false);//Addressables.DownloadDependenciesAsync(keys, false);
            while (downloadDependenciesHandle.Status == AsyncOperationStatus.None)
            
                Debug.Log("当前下载进度:" + downloadDependenciesHandle.GetDownloadStatus().Percent);
                 yield return null;
            
            if (downloadDependenciesHandle.Status == AsyncOperationStatus.Succeeded)
            
                Debug.Log("download success");
            
            else Debug.Log("download failed");
            Addressables.Release(downloadDependenciesHandle);    
            onCheckFinish?.Invoke(checkStatus);
    

    /// <summary>
    /// »ñÈ¡µ¥¸ökey¶ÔÓ¦×ÊÔ´ÏÂÔØ´óС
    /// </summary>
    /// <param name="key"></param>
    /// <param name="onComplete"></param>
    /// <param name="onfailed"></param>
    public void GetDownloadSize(object key, Action<long> onComplete, Action onfailed = null)
    
        var sizeHandle = Addressables.GetDownloadSizeAsync(key.ToString());
        sizeHandle.Completed += (result) => 
            if (result.Status == AsyncOperationStatus.Succeeded)
            
                var downloadSize = result.Result;
                onComplete?.Invoke(downloadSize);
            
            else onfailed?.Invoke();
            Addressables.Release(sizeHandle);
        ;
    
     public AsyncOperationHandle Download(object key, Action onComplete, Action onFailed   = null)
    
        var downloadHandle = Addressables.DownloadDependenciesAsync(key.ToString(), true);
        downloadHandle.Completed += (result) => 
            if (result.Status == AsyncOperationStatus.Succeeded)
             
                onComplete?.Invoke();
            
            else onFailed?.Invoke();
        ;
        return downloadHandle;
    


资源加载

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AssetManager : MonoBehaviour

    public AssetReference assetReference;
    [AssetReferenceUILabelRestriction("HD")]
    public AssetReference assetReferenceHD;
    public AssetReferenceGameObject assetReferenceGameObject;
    public AssetReferenceT<Texture> textureAsset;

    //private void Awake()
    //
    //    Debug.Log("");
    //

    void Start()
    
        //AsyncOperationHandle<GameObject> res = assetReferenceGameObject.LoadAssetAsync();
        //res.Completed += Res_Completed;
        DontDestroyOnLoad(this.gameObject);
        // LoadByName("Prefab1");
        
        AddressableManager.instance.onCheckFinish += Instance_onCheckFinish;
        StartCoroutine(AddressableManager.instance.CheckUpadate());
    

    private void Instance_onCheckFinish(AsyncOperationStatus status)
    
        Debug.Log("finish status is " + status);
        Debug.Log("Path is " + Application.persistentDataPath);
        if (status == AsyncOperationStatus.Succeeded) 
        
            LoadByName("Prefab3");
            LoadByName("SD");//prefab2
            InstantitateByName("Prefab4");
        
    

    private void Res_Completed(AsyncOperationHandle<GameObject> obj)
    
        if (obj.Status == AsyncOperationStatus.Succeeded)
        
            GameObject gob = Instantiate(obj.Result);
            Transform parent = GameObject.Find("Canvas").GetComponent<Transform>();
            gob.transform.SetParent(parent);
        
    

    private void LoadByName(string name)
    
        Addressables.LoadAssetAsync<GameObject>(name).Completed += (handle) => 
            if (handle.Status == AsyncOperationStatus.Succeeded)
            
                GameObject gob = Instantiate(handle.Result, GameObject.Find("Canvas").GetComponent<Transform>());
                Debug.Log($"加载资源完毕:gob.name");
            else Debug.Log($"加载资源失败:name");

        ;
    

    private void InstantitateByName(string name)
    
        Addressables.InstantiateAsync(name).Completed += (handle) => 
            if (handle.Status == AsyncOperationStatus.Succeeded)
            
                GameObject gob = handle.Result;
                gob.transform.SetParent(GameObject.Find("Canvas").GetComponent<Transform>());
                gob.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
                Debug.Log("实例化对象创建完毕" + gob.name);
            else Debug.Log($"加载资源失败:name");
        ;
    




配置文件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ConfigManager 

    public static string CdnUrl = "http://192.168.133.144/Files/dev";
    //public static string RemoteCachePath  get  return Application.persistentDataPath + "/android";  
    public static string RemoteCachePath  get 
#if UNITY_EDITOR
            return "AddresableAsset/android";
#else
            return Application.persistentDataPath+"/AddresableAsset"; 
#endif

        
    


以上是关于Unity之Addressable使用注意事项的主要内容,如果未能解决你的问题,请参考以下文章

Unity 之 Addressable可寻址系统 -- 资源加载和释放 -- 进阶

Unity 之 Addressable可寻址系统 -- 资源加载和释放 -- 进阶

Unity 之 Addressable可寻址系统 -- 可寻址系统使用介绍 -- 入门

Unity 之 Addressable可寻址系统 -- 可寻址系统使用介绍 -- 入门

Unity 之 Addressable可寻址系统 -- 可寻址系统使用介绍 -- 入门

Unity 之 Addressable可寻址系统 -- 资源远程加载 | 资源预下载