Unity Addressables 简易加载应用(三)

981 阅读5分钟

AddressableAssetSettings设置

首先我们需要设置一下构建后数据的存放位置,打开前文所述的Addressables Profiles进行设置,这里仅修改默认配置Default中的Remote项,当然你也可以通过左上方Create创建新的配置修改和选择(别忘了修改Profile In Use选择哟),下拉列表选中自定义,修改RemoteLoadPath(远程加载地址)与RemoteBuildPath(远程构建存放地址),保持地址一致,最好使用绝对路径方便测试。 image.png image.png

这里需要勾选Build Remote Catalog,将Build&Load Paths选中Remote,这里的Remote其实就是刚刚配置Default中的Remote项地址。该项其实就是创建远程缓存数据,需要勾选确认创建,并选择地址存放和加载。最下方Only update catalogs manually取消勾选,它在勾选下当远程资源更新时,本地不会主动更新,而是需要我们手动触发,暂时让它自动更新。 image.png

Default Local Group设置

选中你的Addressables Groups中的默认分组Default Local Groupimage.png image.png

  • Prevent Updates取消勾选,这样该Group后面可以针对变化内容进行更新构建。
  • Build&Load Paths构建和加载地址,选择Remote地址。
  • Include in Build需要勾选,这样初始整包会包含这个Group
  • Cache Clear Behavior这里选择新版本时进行清理。
  • Bundle Mode选择Pack Separately为每个资源单独打Bundle,方便检查。
  • Bundle Naming Mode选择Filename方便检查,且同名会替换旧资源。

测试文件夹分类

这里直接展示最终所需的文件夹和其中的内容,下文会描述他们的作用以及创建步骤。 其中的图片资源需要自己任意找两张尽量相同大小的图片即可,后续会进行替换展示。 image.png

测试界面创建

首先创建三个UI组件里的Button组件,CloseBtn是准备用来关闭应用的,LoadBtn是用来进行加载展示图片的prefabChangeBtn是用来改变对应prefab中的图片资源,最后我们创建展示图片用的Image节点,将其中一张图片拖拽入Image节点的Source Image处进行展示,该节点其实是后面需要Addressables系统中动态加载的prefab节点,创建好后展示如下。 PS:记得将Image节点拖入Prefab文件夹中形成预制件,同时删除Canvas节点下的Image节点噢。 image.png

导入所需资源

需要将展示图片的Image导入Addressables系统中,这里添加入Default组,可以通过拖拽,或勾选prefab栏中顶部的Addressable进行添加,然后将展示的那张图片也导入其中,另外一张图片暂时不导入,等后续将它通过更新的方式上传过去。 image.png

代码内容

首先需要在Script文件夹下创建C#文件,当前命名是StartTest.cs,将其拖拽到Canvas节点上成为它的代码组件,以下是实际代码内容: image.png

using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  
using UnityEngine.AddressableAssets;  
using UnityEngine.ResourceManagement.AsyncOperations; 
using UnityEngine.UI; 
  
public class StartTest : MonoBehaviour  
{  
    // 关闭按钮
    public Button CloseBtn;
    // 加载按钮
    public Button LoadBtn;
    // 替换按钮
    public Button ChangeBtn;
    // 设置为Addressables中Prefab的地址
    public string PrefabAddress;
    // 设置为Addressables中Sprite的地址
    public string SpriteAddress;
    private AsyncOperationHandle<GameObject> prefabHandle;
    private AsyncOperationHandle<Sprite> spriteHandle;
    private GameObject backGround;
  
    void Start()  
    {  
        // 初始化Addressables系统(本身会在第一次调用api时初始化,也可以自己在合适的位置提前调用)  
        Addressables.InitializeAsync();

        // 注册关闭按钮的点击事件
        CloseBtn.onClick.AddListener(() => {
            Application.Quit();
        });

        // 注册加载按钮的点击事件
        LoadBtn.onClick.AddListener(() => {
            // 加载Prefab
            LoadPrefab(PrefabAddress);
        });

        // 注册替换按钮的点击事件
        ChangeBtn.onClick.AddListener(() => {
            // 加载Sprite
            LoadSprite(SpriteAddress);
        });

    }  
  
    void LoadPrefab(string address)  
    {  
        // 使用Addressables系统异步加载Prefab  
        prefabHandle = Addressables.LoadAssetAsync<GameObject>(address);  
        prefabHandle.Completed += HandleOnPrefabLoaded;  
    }  
  
    void HandleOnPrefabLoaded(AsyncOperationHandle<GameObject> handle)  
    {  
        if (handle.Status == AsyncOperationStatus.Succeeded)  
        {  
            // Prefab加载成功,实例化Prefab  
            backGround = Instantiate(handle.Result, transform);  
        }  
        else  
        {  
            // 处理加载失败的情况  
            Debug.LogError($"Failed to load prefab: {handle.OperationException}");  
        }  
    }

    void LoadSprite(string address)  
    {  
        // 使用Addressables系统异步加载Sprite  
        spriteHandle = Addressables.LoadAssetAsync<Sprite>(address);  
        spriteHandle.Completed += HandleOnSpriteLoaded;  
    }

    void HandleOnSpriteLoaded(AsyncOperationHandle<Sprite> handle)  
    {  
        if (handle.Status == AsyncOperationStatus.Succeeded)  
        {  
            // Sprite加载成功,替换图片
            Debug.Log("Sprite加载成功,替换图片");
            backGround.GetComponent<Image>().sprite = handle.Result;
        }  
        else  
        {  
            // 处理加载失败的情况  
            Debug.LogError($"Failed to load sprite: {handle.OperationException}");  
        }  
    }
  
    void OnDestroy()  
    {  
        // 如果Prefab仍在加载中,取消加载并释放句柄  
        if (prefabHandle.IsValid())  
        {  
            Addressables.Release(prefabHandle);  
        }

        // 如果Sprite仍在加载中,取消加载并释放句柄
        if (spriteHandle.IsValid())  
        {  
            Addressables.Release(spriteHandle);  
        }

        // 如果Prefab实例仍然存在,则销毁它  
        if (backGround != null)  
        {  
            Destroy(backGround);  
        }
    }  
}

构建打包

通过编辑器左上方 File -> Build Settings 打开构建设置,如下图进行设置,最后点击Build按钮进行创建。(构建结果可以创建一个文件夹放入其中,这里我是TEST项目根目录下的Out文件夹) image.png 打包完成后,我们分别可以去对应路径查看构建后的文件:

  • TEST\ServerData\StandaloneWindows64:存放构建的Bundles,目前只有预制件和图片。
  • TEST\Assets\AddressableAssetsData\Windows:生成.bin记录文件。
  • TEST\Out:拿来存放构建整包应用的文件夹。

双击TEST\Out\TEST.exe文件运行构建后的应用,然后点击屏幕中的Load按钮,这时候Image将会被Addressables系统的apiBundle中加载并实例化展示出来,就可以看到阿尼亚遇到食物兴奋的表情。如果这个时候我们继续点击Change按钮,就会弹出报错提示(构建设置需要选择Development Build),找不到我们填入的第二张图片,因为我们一开始并没有将它导入Addressables的组中,接下来我们将进行远程数据的更新,让已经生成的应用能从远端更新下来对应的图片进行替换展示。

更新构建

将第二张图片也导入进Default组,加入Addressables的管理,然后点击右侧的 Build -> Update a Previous Build 进行更新构建,这样远端就会更新到第二张图片资源。 image.png image.png

等待更新构建完成后,我们再次去Out目录下启动TEST.exe应用,依次点击Load按钮,展示第一张图,Change按钮展示第二张图,这时第二张图就已经能从远端拉取到了。