当前位置: 首页 > article >正文

Unity热更新 之 Addressables(1) 资源基础加载

   时隔多日,咩咩正式开启网络与热更新部分的学习,劲啊 很劲啊!

        本文内容整合包括但不限于 Unity唐老狮,Unity官方手册,部分网络资源与AI工具

                                仅作学习笔记交流,不做任何商业用途,侵权删

        Addressables是unity官方提供,可以理解为对AssetBundle进行封装与优化的可视化工具, 所以需要对AssetBundle有一定了解,见下链接:Unity 热更新 之 一篇文章完全入门AssetBundle-CSDN博客

        版本:Unity6

        模板:任意(演示模板为:3D核心 渲染管线为URP)

学习前提:有AB包基础,知道委托和事件,知道匿名函数怎么用

加油站:C# & Unity 面向对象补全计划 之 委托-CSDN博客

C# & Unity 面向对象补全计划 之 事件-CSDN博客

C# & Unity 面向对象补全计划 之 匿名函数与Lambda表达式_unity 匿名函数-CSDN博客

目录

1.导入包

2.简单使用方法 

3.加载资源重要API

3.1 AssetReference(仅作了解即可)

3.2 资源加载完成回调与状态判别

3.3动态加载单资源

3.4 动态加载多资源

3.5 多资源加载筛选问题

3.6资源释放

4.练习题


1.导入包

        不墨迹

           工具的窗口路径              为什么中英文掺杂?

        我为了看最新的组件改了中文,但是日常使用为英文,编辑器内改语言就会出现这种bug

2.简单使用方法 

        基础界面  没什么好介绍的,这个工具的英文十分简单,不会的拿翻译软件拍照翻译即可

        以预制体举例添加资源到其中:

        打勾之后点确定,会出现一个新的文件夹Resources_moved

        

        原因:热更新的包是单独打出去的,而放到Resources文件夹会和unity一同打包出去,所以不合适,系统就会创建一个新的文件夹

        看到如下界面

        你可以点New 创建新的包,(包名自定义)

        然后把资源放里面去,就相当于AssetBundle里面的包的概念

 

        你可能发现你的资源名字很长,不要紧 右键点击简化可寻址资源名即可

        可以给资源打标签,一个资源可以有多个标签

 

3.加载资源重要API

3.1 AssetReference(仅作了解即可)

        AssetReference可以理解为Addressables中的资源标识类,他可以存储对不同可寻址资源的引用,并且通过它提供的方法(如加载、实例化资源等操作)来使用这些资源 

       举个例子:

声明一个该变量

 public AssetReference anyTypeAsset;

就可以从外部去拖 

可以接受的内容包含了整个可寻址资源的资产

     可以泛型加载,且通常是异步加载(异步加载的本质是后台开新线程去做,所以至少要等主进程的一帧后才会完成),其有返回值AsyncOperationHandle<TObject>

 //加载资源会有AsyncOperationHandle 返回值
 AsyncOperationHandle<GameObject> returnObj = anyTypeAsset.LoadAssetAsync<GameObject>();

        下面将会对returnObj进行操作

3.2 资源加载完成回调与状态判别

      资源加载后的返回值有Completed事件

注意描述:Completion event for the internal operation.  If this is assigned on a completed operation, the callback is deferred until the LateUpdate of the current frame.

内部操作的完成事件。如果在一个已完成的操作上赋值,回调将被延迟到当前帧

        当这个事件被完成之后无论成功与失败都会执行回调函数,之后通过状态判断资源是否被加载成功
 

 returnObj.Completed += Callback;


private void Callback(AsyncOperationHandle<GameObject> obj) {

    if (obj.Status == AsyncOperationStatus.Succeeded) {

        Instantiate(obj.Result);

    }
    else if (obj.Status == AsyncOperationStatus.Failed) {

        Debug.Log("资源加载失败");

    }
}

    其中状态是一个枚举

        另外上述的代码可以用匿名函数的方式 一步到位


      anyTypeAsset.LoadAssetAsync<GameObject>().Completed += ((obj) => {

          if (obj.Status == AsyncOperationStatus.Succeeded) {

              Instantiate(obj.Result);

          }
          else if (obj.Status == AsyncOperationStatus.Failed) {

              Debug.Log("资源加载失败");

          }
      });

3.3动态加载单资源

        在实际项目之中,3.1并不常用,而3.3和3.4两个部分的api用是非常多的,其实也非常简单

        就是用Addressables进行异步加载,也是可以通过泛型进行类型的准确加载,但是可以通过标签去加载

  Addressables.LoadAssetAsync<GameObject>("Cube");
  Addressables.LoadAssetAsync<GameObject>("A");

        返回值还是 AsyncOperationHandle,所以3.2的资源加载的回调和状态判别仍旧是一样的

 Addressables.LoadAssetAsync<GameObject>("A").Completed += ((obj) => {

     if (obj.Status == AsyncOperationStatus.Succeeded) {

         Instantiate(obj.Result);

     }
     else if (obj.Status == AsyncOperationStatus.Failed) {

         Debug.Log("资源加载失败");

     }
 });

        那么有趣的来了,如果标签一样那么其会加载哪一个?

        是你该组别中的第一个有该标签的资源         这个时候就需要动态加载多个资源的方法了

3.4 动态加载多资源

        Addressables.LoadAssetAsync

        Addressables.LoadAssetsAsync,多资源比单资源加载就多个s,返回值就变成了 <IList<TObject>>

    public static AsyncOperationHandle<IList<TObject>> LoadAssetsAsync<TObject>(string key, Action<TObject> callback = null)
    {
        return m_Addressables.LoadAssetsAsync(new List<string>() { key }, callback, MergeMode.None, true);
    }
  //加载多个资源,受到泛型约束
  AsyncOperationHandle<IList<GameObject>> handle = Addressables.LoadAssetsAsync<GameObject>("A");
  handle.Completed += (obj) => {
      foreach (var item in handle.Result) {
          if (obj.Status == AsyncOperationStatus.Succeeded) {

              Instantiate(item);

          }
          else if (obj.Status == AsyncOperationStatus.Failed) {

              Debug.Log("资源加载失败");

          }
      }
  };

来看一下结果:

     

3.5 多资源加载筛选问题

        多资源加载有个重要的重载,其诞生的原因为多资源中名字与标签的重合问题,就比如我的包有如下内容排布 ,这样只通过包和标签去加载的话就成了问题

        比如用两个Addressables.LoadAssetsAsync<T>去加载,或者先全部加载成Objcet后再分别装箱拆箱区分,这样十分麻烦

        那么就会用以下重载 

    List<string> strs = new List<string>() { "Cube", "A" };
    Addressables.LoadAssetsAsync<Object>(strs, (obj) => {
        print(obj.name);
    }, Addressables.MergeMode.Intersection);

    //参数一:想要加载资源的条件列表(资源名、Lable名)
    //参数二:每个加载资源结束后会调用的函数,会把加载到的资源传入该函数中
    //参数三:可寻址的合并模式,用于合并请求结果的选项。
    //如果键(Cube,A)映射到结果([1,2,3,4],[1,3,4]),数字代表不同的资源
    //None:不发生合并,将使用第一组结果 结果为[1,2,3,4]
    //UseFirst:应用第一组结果 结果为[1,2,3,4]
    //Union:合并所有结果 结果为[1,2,3,4]
    //Intersection:使用相交结果 结果为[1,3,4]
    //参数四:如果为true表示当资源加载失败时,会自动将已加载的资源和依赖都释放掉
    //      如果为false,需要自己手动来管理释放

     

3.6资源释放

        这里需要注意的一点就是,释放的是资源异步加载后的返回值

AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>("Cube");
Addressables.Release(handle);

4.练习题

        唐老师的对3.4与3.5的封装 ,仅供参考

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

public class Exercises : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region Lesson5 练习题
        //尝试自己写一个Addressables资源管理器
        //帮助我们通过名字加载单个资源或场景,并管理资源相关内容

        //AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>("Cube");
        //handle.Completed += (obj) => {
        //    //加载成功后的逻辑处理

        //    Addressables.Release(obj);
        //};
        //分析:
        //1.资源动态加载可以通过返回的对象AsyncOperationHandle<>(异步操作句柄) 添加完成监听来处理加载后的资源
        //2.释放资源时也是通过释放返回的对象AsyncOperationHandle<>(异步操作句柄) 来进行释放
        //3.如果分散在各脚本中自己管理资源难免显得太过凌乱,所以我们可以通过一个资源管理器来管理所有的异步加载返回对象AsyncOperationHandle<>(异步操作句柄)

        //所以如果我们要自己写一个Addressables资源管理器,主要就是用来管理AsyncOperationHandle<>对象的

        //AddressablesMgr.Instance.LoadAssetAsync<GameObject>("Cube", (obj) =>
        //{
        //    Instantiate(obj.Result);
        //});

        //AddressablesMgr.Instance.LoadAssetAsync<GameObject>("Cube", (obj) =>
        //{
        //    Instantiate(obj.Result, Vector3.right * 5, Quaternion.identity);
        //    //使用完资源后 移除资源
        //    AddressablesMgr.Instance.Release<GameObject>("Cube");
        //});
        #endregion

        #region Lesson6 练习题
        //尝试在上一个Addressables资源管理器中
        //提供一个批量或指定加载释放资源的方法
        //List<string> strs = new List<string>() { "Cube", "HD" };
        //Addressables.LoadAssetsAsync<Object>(strs, (obj) => {
        //    print(obj.name);
        //}, Addressables.MergeMode.Intersection);

        //AddressablesMgr.Instance.LoadAssetAsync<Object>(Addressables.MergeMode.Intersection, (obj) =>
        //{
        //    print("1" + obj.name);
        //}, "Cube", "SD");

        //AddressablesMgr.Instance.LoadAssetAsync<Object>(Addressables.MergeMode.Intersection, (obj) =>
        //{
        //    print("2" + obj.name);
        //}, "Cube", "SD");

        #endregion
    }

    // Update is called once per frame
    void Update()
    {
        //创建对象 记录异步操作句柄
        if (Input.GetKeyDown(KeyCode.Space))
        {
            AddressablesMgr.Instance.LoadAssetAsync<GameObject>("Cube", (obj) =>
            {
                Instantiate(obj.Result);
            });
        }

        //从创建对象中 释放异步操作句柄资源
        if (Input.GetKeyDown(KeyCode.Q))
        {
            AddressablesMgr.Instance.Release<GameObject>("Cube");
        }
    }
}


http://www.kler.cn/a/428394.html

相关文章:

  • 当 Facebook 窥探隐私:用户的数字权利如何捍卫?
  • C++----STL(list)
  • JAVA毕业设计210—基于Java+Springboot+vue3的中国历史文化街区管理系统(源代码+数据库)
  • 回首2024,展望2025
  • MyBatis Plus 的 InnerInterceptor:更轻量级的 SQL 拦截器
  • 禁止 iOS 系统浏览器双指放大页面
  • Vue CLI的作用
  • 关于HTTP DEBUGGER PRO的DURATION列一点理解
  • 在Linux(ubuntu22.04)搭建rust开发环境
  • Java-19 深入浅出 MyBatis - 用到的设计模式 源码剖析 代理设计模式
  • 【数据库】复习
  • import是如何“占领满屏“
  • QT模型/视图结构:ListModel与TableModel
  • 前端工程化面试题(一)
  • Apache AGE:基于PostgreSQL的图数据库
  • 如何通过AI“一键生成PPT”提升工作效率与创意表达
  • vscode配置django环境并创建django项目(全图文操作)
  • DemoFusion 技术浅析(三):渐进式上采样
  • MR30分布式IO模块赋能喷水织机
  • 自动驾驶3D目标检测综述(五)
  • 【Python】报错:Statement seems to have no effect
  • 文件操作---文件IO与标准IO
  • ftp服务器搭建-安装、配置及验证
  • 使用Redis的Bitmap实现签到功能
  • Java项目实战II基于微信小程序的消防隐患在线举报系统(开发文档+数据库+源码)
  • Kafka 常见面试题深度解析