Unity-Adressable打包热更

博客 动态
0 194
羽尘
羽尘 2022-05-15 21:59:16
悬赏:0 积分 收藏

Unity-Adressable打包热更

Addressable是Unity推出的打ab包方案,自动依赖;

不需要手动写AB打包方案,不需要关心依赖;

提供本地远程服务异步加载;

打包粒度可调节;

1.Group

Addressable打包需要先将资源放入Group中,按group来打包,每个group对应一个ScriptableObject配置可调节;

Group可以调节包体是本地加载还是远程服务器加载;

可调节压缩方式,是否缓存,请求超时时间等;

image-20220515195301242

打包粒度:

同一Group可选择一起打包,完全分开打包和按标签打包;

同一标签会打成一个ab包,一个资源可选择多个标签;

这里设置Group中的打包粒度;

image-20220515195444849

2.Build

直接将资源拖进对应的分组;

image-20220515200525999

或在资源Inspector界面勾选addressable,资源会自动根据路径生成一个Name(用于加载);

image-20220515200446115

打包资源点击Build-NewBuild-Default Build;

Update是再打过包的基础上,更新资源,热更新时候用到;

image-20220515200032183

Profiles界面设置本地远程加载资源的路径

image-20220515200637866

Addressable提供了本地服务器hosting界面,设置好端口点enable即可,或者使用其他服务器测试也可;

3.Load

3.1加载方式

根据Name加载

Addressables加载需要上面Group中资源的Name=>参数path;

LoadAssetAsync加载完成后返回handle,可以用于释放资源;

因为异步加载资源无法及时返回加载后的资源,可以使用委托加载完成后,接收或操作资源;

public static AsyncOperationHandle<GameObject> LoadPrefab(string path, Action<GameObject> onComplete, bool isInstantiate = true){    var handle = Addressables.LoadAssetAsync<GameObject>(path);    handle.Completed += (obj) =>    {        GameObject go = obj.Result;        if (isInstantiate)        {            go = GameObject.Instantiate(go);            go.name = go.name.Substring(0, go.name.Length - 7);        }        onComplete(go);    };    return handle;}//提供直接实例化函数Addressables.InstantiateAsync("Assets/Prefabs/Cube.prefab").Completed += (obj) =>{    // 已实例化的物体    GameObject cubeObj = obj.Result;};

可以使用async,await方式加载资源,可以直接接收结果;C#async&await&Task

但是webgl可能无法调用,js不支持多线程;

private async void InstantiateCube(){	GameObject prefabObj = await Addressables.LoadAssetAsync<GameObject>("Assets/Prefabs/Cube.prefab").Task;	GameObject cubeObj = Instantiate(prefabObj);			// InstantiateAsync方法	// GameObject cubeObj = await Addressables.InstantiateAsync("Assets/Prefabs/Cube.prefab").Task;}
根据AssetReference加载

在Inspector界面,将需要加载的文件拖动赋值给AssetReference;

public AssetReference spherePrefabRef;void Start(){   	spherePrefabRef.LoadAssetAsync<GameObject>().Completed += (obj) => 	{		GameObject spherePrefab = obj.Result;		GameObject sphereObj = Instantiate(spherePrefab);	};}//通过标签引用,可以批量加载同标签所有资源AssetLabelReference label;Addressables.LoadAssetsAsync<Texture2D>(textureLabel, (t) =>{	    //每加载完一次会回调一次    Logger.Log(t.name);});

3.2加载类型

上面Prefab加载已经写了;下面来加载图片,音频和场景;

//图片Addressables.LoadAssetAsync<Texture2D>("Assets/Textures/a.jpg").Completed += (obj) =>{    Texture2D tex2D = obj.Result;    img.texture = tex2D;    img.GetComponent<RectTransform>().sizeDelta = new Vector2(tex2D.width, tex2D.height);};//textrue2D转spriteTexture2D tex;Sprite sp = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero);//场景var handle = Addressables.LoadSceneAsync("Assets/Scenes/GameScene.unity");if (handle.Status == AsyncOperationStatus.Failed){    Debug.LogError("ERROR: " + handle.OperationException.ToString());    yield break;}//加载百分比while (!handle.IsDone){	float percentage = handle.PercentComplete;	yield return null;}//音频Addressables.LoadAssetAsync<AudioClip>("Assets/Scenes/1.ogg");

3.3资源释放

加载的资源销毁组件后并不会销毁资源;(prefab不用如此释放)

直接释放资源,或者释放handle都可;

Addressables.Release(tex2D);Addressables.Release(handle); 

3.4PlayMode:

第一个不使用AB加载,开发时候用;

第二个模拟ab加载;

第三个会根据LoadPath去加载真实的AB包读取资源,必须先Build;

image-20220515195628905

4.热更新

Addressables更新流程:

CheckForCatalogUpdates ->检测更新;

UpdateCatalogs -> 下载Catalogs文件;

GetDownloadSizeAsync ->获取更新资源大小;

DownloadDependenciesAsync->下载更新资源;

中途断网强退,使用AsyncOperationHandle的Status判断;

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.AddressableAssets;using UnityEngine.AddressableAssets.ResourceLocators;using UnityEngine.ResourceManagement.AsyncOperations;using UnityEngine.UI;public class CheckUpdateAndDownload : MonoBehaviour{    public Text updateText;    void Start()    {        StartCoroutine(UpdateAddressable());    }    private IEnumerator UpdateAddressable()    {        AsyncOperationHandle<IResourceLocator> initHandle = Addressables.InitializeAsync();        yield return initHandle;        // 检测更新        var checkHandle = Addressables.CheckForCatalogUpdates(true);        yield return checkHandle;        if (checkHandle.Status != AsyncOperationStatus.Succeeded)        {            Debug.LogError("CheckForCatalogUpdates Error\n" + checkHandle.OperationException.ToString());            yield break;        }        if (checkHandle.Result.Count > 0)        {            var updateHandle = Addressables.UpdateCatalogs(checkHandle.Result, true);            yield return updateHandle;            if (updateHandle.Status != AsyncOperationStatus.Succeeded)            {                Debug.LogError("UpdateCatalogs Error\n" + updateHandle.OperationException.ToString());                yield break;            }            // 更新列表迭代器            List<IResourceLocator> locators = updateHandle.Result;            foreach (var locator in locators)            {                List<object> keys = new List<object>();                keys.AddRange(locator.Keys);                // 获取待下载的文件总大小                var sizeHandle = Addressables.GetDownloadSizeAsync(keys.GetEnumerator());                yield return sizeHandle;                if (sizeHandle.Status != AsyncOperationStatus.Succeeded)                {                    Debug.LogError("GetDownloadSizeAsync Error\n" + sizeHandle.OperationException.ToString());                    yield break;                }                long totalDownloadSize = sizeHandle.Result;                updateText.text = updateText.text + "\ndownload size : " + totalDownloadSize;                Debug.Log("download size : " + totalDownloadSize);                if (totalDownloadSize > 0)                {                    // 下载                    var downloadHandle = Addressables.DownloadDependenciesAsync(keys, true);                    while (!downloadHandle.IsDone)                    {                        if (downloadHandle.Status == AsyncOperationStatus.Failed)                        {                            Debug.LogError("DownloadDependenciesAsync Error\n" + downloadHandle.OperationException.ToString());                            yield break;                        }                        // 下载进度                        float percentage = downloadHandle.PercentComplete;                        Debug.Log($"已下载: {percentage}");                        updateText.text = updateText.text + $"\n已下载: {percentage}";                        yield return null;                    }                    if (downloadHandle.Status == AsyncOperationStatus.Succeeded)                    {                        Debug.Log("下载完毕!");                        updateText.text = updateText.text + "\n下载完毕";                    }                }            }        }        else        {            updateText.text = updateText.text + "\n没有检测到更新";        }    }}
posted @ 2022-05-15 20:57 小紫苏 阅读(8) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员