Addressables学习笔记

2023-11-07

运行环境

Unity 2020.3.3f1

Addressable 1.16.16

资源引用

AssetReference

资产引用

参考

AssetReference

属性

Asset

加载的资产

AssetReferenceT

泛型资产引用

参考

AssetReferenceT

AssetLabelReference

资产标签引用

用来加载一组带有该标签的资产

参考

AssetLabelReference

AsyncOperationHandle

异步加载返回的类型

属性

Result

异步加载的结果,加载失败时为null

Status : AsyncOperationStatus

  • None(进行中)
  • Succeeded(成功)
  • Failed(失败)

IsDone : bool

Status成功或失败时为 true

PercentComplete : float

完成的百分比(0~1)

Addressables API

InstantiateAsync(异步实例化)

using UnityEngine;
using UnityEngine.AddressableAssets;

public class BasicReference : MonoBehaviour
{
    public AssetReference baseCube;

    public void SpawnThing()
    {
        // 使用 Addressable Name 实例化(区分大小写)
        Addressables.InstantiateAsync("Assets/Prefabs/Cube.prefab");
        // 使用 AssetReference 实例化
        Addressables.InstantiateAsync(baseCube);
        // 使用 RuntimeKey 实例化
        Addressables.InstantiateAsync(baseCube.RuntimeKey);
        // 使用 AssetReference实例方法 实例化
        baseCube.InstantiateAsync();
    }
}

注意点

  • Addressable Name 区分大小写

ReleaseInstance(释放实例)

using UnityEngine;
using UnityEngine.AddressableAssets;

public class SelfDestruct : MonoBehaviour
{
    public float lifetime = 2f;

    private void Start()
    {
        Invoke(nameof(Release), lifetime);
    }

    private void Release()
    {
        // 释放实例
        if (!Addressables.ReleaseInstance(gameObject))
        {
            Destroy(gameObject);
        }
    }
}

注意点

  • Addressables 实例化的对象,使用 Addressables.ReleaseInstance 释放实例
  • Instantiate 实例化的对象,使用 Destroy 销毁对象

LoadAssetAsync(异步加载资产)

轮询

using System;
using UnityEngine;
using UnityEngine.AddressableAssets;

public class FilteredReferences : MonoBehaviour
{
    [Serializable]
    public class AssetReferenceMaterial : AssetReferenceT<Material>
    {
        public AssetReferenceMaterial(string guid) : base(guid)
        {
        }
    }

    public AssetReferenceGameObject leftObject;
    public AssetReferenceGameObject rightObject;
    public AssetReferenceMaterial spawnMaterial;
    public AssetReferenceMaterial midMaterial;
    public AssetReferenceMaterial lateMaterial;

    public Vector3 leftPosition;
    public Vector3 rightPosition;

    private MeshRenderer m_LeftMeshRender;
    private MeshRenderer m_RightMeshRender;
    private int m_FrameCounter = 0;


    private void Start()
    {
        leftObject.LoadAssetAsync();
        rightObject.LoadAssetAsync();
        spawnMaterial.LoadAssetAsync();
        midMaterial.LoadAssetAsync();
        lateMaterial.LoadAssetAsync();
    }

    private void FixedUpdate()
    {
        m_FrameCounter++;
        switch (m_FrameCounter)
        {
            case 20:
            {
                if (leftObject.Asset)
                {
                    var leftGo = Instantiate(leftObject.Asset, leftPosition, Quaternion.identity) as GameObject;
                    m_LeftMeshRender = leftGo.GetComponent<MeshRenderer>();
                }
                
                if (rightObject.Asset)
                {
                    var rightGo = Instantiate(rightObject.Asset, rightPosition, Quaternion.identity) as GameObject;
                    m_RightMeshRender = rightGo.GetComponent<MeshRenderer>();
                }

                if (spawnMaterial.Asset && m_LeftMeshRender != null && m_RightMeshRender != null)
                {
                    m_LeftMeshRender.material = spawnMaterial.Asset as Material;
                    m_RightMeshRender.material = spawnMaterial.Asset as Material;
                }

                break;
            }
            case 40:
            {
                if (midMaterial.Asset && m_LeftMeshRender != null && m_RightMeshRender != null)
                {
                    m_LeftMeshRender.material = midMaterial.Asset as Material;
                    m_RightMeshRender.material = midMaterial.Asset as Material;
                }

                break;
            }
            case 60:
            {
                m_FrameCounter = 0;
                if (lateMaterial.Asset && m_LeftMeshRender != null && m_RightMeshRender != null)
                {
                    m_LeftMeshRender.material = lateMaterial.Asset as Material;
                    m_RightMeshRender.material = lateMaterial.Asset as Material;
                }

                break;
            }
        }
    }

    private void OnDisable()
    {
        // note that this may be dangerous, as we are releasing the asset without knowing if the instances still exist.
        // sometimes that's fine, sometimes not.
        leftObject.ReleaseAsset();
        rightObject.ReleaseAsset();
        spawnMaterial.ReleaseAsset();
        midMaterial.ReleaseAsset();
        lateMaterial.ReleaseAsset();
    }
}

回调

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

public class ListOfReferences : MonoBehaviour
{
    public List<AssetReference> shapes;

    private bool m_IsReady = false;
    private int m_ToLoadCount;

    private int currentIndex = 0;


    private void Start()
    {
        m_ToLoadCount = shapes.Count;
        foreach (var shape in shapes)
        {
            shape.LoadAssetAsync<GameObject>().Completed += OnShapeLoaded;
        }
    }

    private void OnShapeLoaded(AsyncOperationHandle<GameObject> obj)
    {
        m_ToLoadCount--;
        if (m_ToLoadCount <= 0)
        {
            // 资源全部加载完成,准备就绪
            m_IsReady = true;
        }
    }

    public void SpawnAThing()
    {
        if (!m_IsReady)
        {
            Debug.Log("还未准备就绪");
            return;
        }

        for (int count = 0; count <= currentIndex; count++)
        {
            Instantiate(shapes[currentIndex].Asset);
        }

        currentIndex = (currentIndex + 1) % shapes.Count;
    }

    private void OnDestroy()
    {
        foreach (var shape in shapes)
        {
            shape.ReleaseAsset();
        }
    }
}

LoadAssetsAsync(异步加载多个资产)

使用 AssetLabelReference 加载

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

public class BasicReference : MonoBehaviour
{
    public AssetLabelReference assetLabelReference;

    public void SpawnThing()
    {
        // 使用 AssetLabelReference 加载
        Addressables.LoadAssetsAsync<GameObject>(assetLabelReference, OnLoadedAsset)
            .Completed += OnCompleted;

        // 使用 RuntimeKey 加载
        Addressables.LoadAssetsAsync<GameObject>(assetLabelReference.RuntimeKey, OnLoadedAsset)
            .Completed += OnCompleted;
    }

    /// <summary>
    /// 全部资产加载完成回调
    /// </summary>
    /// <param name="handle"></param>
    private void OnCompleted(AsyncOperationHandle<IList<GameObject>> handle)
    {
        foreach (var item in handle.Result)
        {
            Debug.Log($"实例化: {item}");
            Instantiate(item);
        }

        Addressables.Release(handle);
    }

    /// <summary>
    /// 资产加载完成回调
    /// </summary>
    /// <param name="obj">加载完成的资产</param>
    private void OnLoadedAsset(GameObject obj)
    {
        Debug.Log($"加载完成: {obj}");
    }
}

指定 label 加载

using UnityEngine;
using UnityEngine.AddressableAssets;

public class BasicReference : MonoBehaviour
{
    public void SpawnThing()
    {
        // 使用 label 加载(区分大小写)
        Addressables.LoadAssetsAsync<GameObject>("big", null)
            .Completed += handle =>
        {
            foreach (var item in handle.Result)
            {
                Debug.Log($"实例化: {item}");
                Instantiate(item);
            }

            Addressables.Release(handle);
        };
    }
}

指定 addressable name 与 label 加载

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

public class BasicReference : MonoBehaviour
{
    public void SpawnThing()
    {
        // var key = new List<string> {"big", "Assets/Prefabs/Cube.prefab"}; // key区分大小写,字符串顺序无所谓
        var key = new List<string> {"Assets/Prefabs/Cube.prefab", "big"}; // 顺序调换后依旧可以加载
        
        // 加载所有 (addressable name = "Assets/Prefabs/Cube.prefab", label = "big") 的GameObject类型资产
        Addressables.LoadAssetsAsync<GameObject>(key, null, Addressables.MergeMode.Intersection)
            .Completed += handle =>
        {
            foreach (var item in handle.Result)
            {
                Debug.Log($"实例化: {item}");
                Instantiate(item);
            }

            Addressables.Release(handle);
        };
    }
}

注意点

  • key区分大小写

  • key的字符串顺序无所谓

  • 使用 带addressable name的key 加载时,第三个参数必须加

LoadSceneAsync(异步加载场景)

using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class AddScenes : MonoBehaviour
{
    public string addressToAdd;
    private Button m_AddButton;
    public TMPro.TMP_Text textArea;
    private SceneInstance m_LoadedScene;
    private bool m_ReadyToLoad = true;

    private void Start()
    {
        m_AddButton = GetComponent<Button>();
        m_AddButton.onClick.AddListener(OnButtonClick);

        textArea.text = "Load " + addressToAdd;
    }

    private void OnButtonClick()
    {
        if (string.IsNullOrEmpty(addressToAdd))
        {
            Debug.LogError("Address To Add not set.");
        }

        else
        {
            if (m_ReadyToLoad)
            {
                Addressables.LoadSceneAsync(addressToAdd, LoadSceneMode.Additive).Completed += OnSceneLoaded;
            }
            else
            {
                Addressables.UnloadSceneAsync(m_LoadedScene).Completed += OnSceneUnloaded;
            }
        }
    }

    private void OnSceneUnloaded(AsyncOperationHandle<SceneInstance> obj)
    {
        if (obj.Status == AsyncOperationStatus.Succeeded)
        {
            textArea.text = "Reload " + addressToAdd;
            m_ReadyToLoad = true;
            m_LoadedScene = new SceneInstance();
        }
        else
        {
            Debug.LogError("Failed to unload scene at address: " + addressToAdd);
        }
    }

    private void OnSceneLoaded(AsyncOperationHandle<SceneInstance> obj)
    {
        if (obj.Status == AsyncOperationStatus.Succeeded)
        {
            textArea.text = "Unload " + addressToAdd;
            m_LoadedScene = obj.Result;
            m_ReadyToLoad = false;
        }
        else
        {
            Debug.LogError("Failed to load scene at address: " + addressToAdd);
        }
    }
}

热更新

流程

  • 编译

    1. 编译 addressables

      • 打开Addressable Groups界面

      • Addressable GroupContent Update Restriction 必须设置为 Can Change Post Release

      • 在界面中选择 Build -> New Build -> Default Build Script

    2. 编译 可执行文件

  • 更新

    1. 更新 addressables中的资产
    2. 更新 之前编译的addressables
      • Addressable Groups界面中,选择 Build -> Update a Previous Build -> [对应的平台]

注意点

  • 编译可执行文件之前需要先编译 addressables
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Addressables学习笔记 的相关文章

  • Unity用Vuforia做AR实现脱卡效果

    有时在识别目标丢失后我们仍希望虚拟物体能够出现在摄像机前 或者到一个特定的位置 我们能对其进行操作 这就是脱卡功能 自带的脱卡功能应该是ExtendedTracking 允许模型在识别图丢失的时候还存在 位置不变 在丢失的时候的位置 这样也
  • unity粒子特效附上贴图后播放动画

    转自 http jingyan baidu com article f96699bbb1a0d6894f3c1b77 html 参考 http www unitymanual com thread 2993 1 1 html dsign a
  • unity game界面按下play会不断闪烁,按下暂停键(pause)或者中止/下一步(step),game界面的画面会接连变化

    没找到答案 改了两个下午的程序 改完还是这样 后来发现是FixedUpdate Update与OnDrawGizmos的问题 OnDrawGizmos是每帧都会绘制 用FixedUpdate理所当然就那啥了 分析的时候 就突然想到是不是这俩
  • 【UGUI】2D头顶血条制作

    前言 近期因为需要制作玩家和敌人头顶的2D血条 查找了很多博客 发现很多都拘束于Canvas的渲染模式必须要设定为ScreenSpace Overlay 还有应该是版本原因 我的是unity2019 1 11f1 用RecttTransfo
  • Unity中loading页加载的实现

    首先创建一个Global cs 使用单例用于存储场景的名字 便于后续脚本的调用 此脚本不必挂载在游戏物体上 using UnityEngine using System Collections public class Global Mon
  • unity制作一个可以自由滑动收缩的历史记录功能。

    公司在做一款模拟经营类的卖车游戏 需要一个简单的历史记录功能 放在左上角 记录最近20条的收入 支出记录 超过2秒不动则收起 收起时展示最近的一个消息记录 用到的组件是ScrollView 使用方法可以参考我写过的一篇博客 ScrollVi
  • unity网络资源导入

    1 找到需要导入的文件 这里导入fbx格式 2 打开unity界面 在Asset目录下创建文件夹FBX 将需要导入的fbx预制体或整个文件夹拖入创建的FBX文件夹下 3 选中需要的fbx预制体并拖至场景中 4 双击定位到当前物体 5 找到需
  • Unity动画控制器animator.CrossFade

    需要特别注意 1 CrossFade虽然可以不用任何逻辑来链接而直接跳转 但是CrossFade只能覆盖其他动画 当当前动画播放完毕而没有跳出这个动画时再次调用CrossFade将会失败 造成动画依旧停在原位 参数animator Cros
  • Unity中UI框架的使用1-添加面板、显示Loading页面

    其中BasePanel和Canvas都是挂在面板的预制物上的 1 导入我们的UI框架 本篇文章中有用的是两个UIPanelType NUIManager和NBasePanel 会放在文章最后供大家使用 2 先将我们做好的Panel设置成预制
  • Unity保存图片到相册

    Unity保存图片到Android相册 Java 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
  • Unity打包WebGL的优化常用操作?

    1 贴图部分优化 如果贴图格式时2048 在不影响画面效果的情况下 改成1024或者5 12 还可以缩小包体 2 压缩和解压缩问题 WebGL打包的时候分三种压缩情况 gzip 比Brotli文件打 但打包快 http和https都支持 B
  • 【Unity步步升】监控与检测物体的各种方案,如:射线、碰撞、挂载等...

    在制作AR模型数值控制方案的时候遇到了检测的问题 学习过程受益匪浅 故今天为大家整理带来一篇监控与检测物体的参考方案集合 目录 一 射线检测 二 物体存在检测 三 碰撞检测 一 射线检测 单射线检测 首先完成搭建场景如下图1 1 我这里用到
  • unity3d切换场景Application.LoadLevel(1)含义

    Application LoadLevel 1 场景ID
  • unity3d image组件不显示

    需要将UI组件放到画布下面
  • 【Unity】运行时创建曲线(贝塞尔的运用)

    Unity 运行时创建线 贝塞尔的运用 1 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线 2 原理介绍 2 1 曲线的创建 unity建立网格曲线可以参考 Unity程序化网格体 的实现方法 主要分为顶点 三角面 U
  • Unity学习笔记

    一 旋转欧拉角 四元数 Vector3 rotate new Vector3 0 30 0 Quaternion quaternion Quaternion identity quaternion Quaternion Euler rota
  • U3D游戏开发中摇杆的制作(UGUI版)

    在PC端模拟摇杆 实现玩家通过控制摇杆让玩家移动 以下是完整代码 using System Collections using System Collections Generic using UnityEngine using Unity
  • 游戏开发常见操作梳理之NPC任务系统

    多数游戏存在任务系统 接下来介绍通过NPC触发任务的游戏制作代码 using System Collections using System Collections Generic using UnityEngine
  • 游戏开发常见操作梳理之NPC药品商店系统(NGUI版)

    后续会出UGUI Json的版本 敬请期待 游戏开发中经常会出现药品商店 实际操作与武器商店类似 甚至根据实际情况可以简化设置 废话不多说 直接上代码 药品商店的源码 using System Collections using Syste
  • 游戏开发中常见系统梳理之背包系统的实现一

    游戏中几乎都存在大大小小的背包系统 接下来我将讲述背包系统具体是如何实现的 完整源码 以下是使用unity NGUI实现 使用txt配置的方法 后续更新UGUI Json实现的背包系统敬请期待 背包中的物品我们常常将其制作成预设体 通过改变

随机推荐

  • 【electron】应用在线升级

    流程 1 设置feedUrl 每次登录应用后更新feedUrl 如果需要灰度测试 可以添加uuid的参数 由服务端判断是否命中 注意 feedUrl需要在checkUpdate之前调用 主进程 初始化 private cancellatio
  • U3D客户端框架之 音效管理器 与 Fmod介绍安装导入Unity

    一 Fmod介绍与安装导入Unity 1 Fmod与Unity内置Audio播放器对比 Unity内置的Audio底层使用的是FMOD 但是功能不够齐全 高级一点的功能如混合 Mix 等无法使用 音效管理应该和Unity工程解耦合 这样子可
  • Python中处理异常和错误

    作为一种强大且灵活的编程语言 Python 提供了许多机制来处理程序运行过程中可能出现的异常和错误 本文将详细介绍如何在 Python 中以 优雅 高效 的方式进行异常处理 并提供实用技巧帮助开发者更好地应对各种情况 无论您是初学者还是有经
  • 单相桥式全控整流电路

    单相全控桥式带电阻负载时的电路 带电阻负载的工作情况 电路分析 闸管VT1和VT4组成一对桥臂 VT2和VT3组成另一对桥臂 在u2正半周 即a点电位高于b点电位 若4个晶闸管均不导通 id 0 ud 0 VT1 VT4串联承受电压u2 在
  • linux echo彩色打印

    定义了三个颜色 把打印的内容加载头和尾巴之间即可 pt head green 033 32 1m pt head red 033 31 1m pt head yellow 033 33 1m pt tail 033 0m echo pt h
  • STM32学习笔记-大小端模式详解

    最低有效字节在最前端的方式 小端法 最高有效字节在最前端的方式 大端法 小端模式 Little Endian 小端模式 Little Endian 也称为Intel顺序 最低有效字节 首先存储 例如 int16数据0x0123467在地址单
  • vue3:使用:图片生成二维码并复制

    实现在 vue3 中根据 url 生成一个二维码码 且可以复制 注 复制功能 navigator clipboard write 只能在安全的localhost 这种安全网络下使用 https中需要添加安全证书 且在域名 例 https w
  • 打印二维、多行的PDF-417条形码控件PDF417 Fonts and Encoder

    PDF417 Fonts and Encoder条形码控件使您可以在带有支持TrueType BDF FON SFP PCL laserjet soft PostScript type 1 Binary及PostScript ASCII字体
  • Qt QT_WIDGETS_LIB宏

    如果定义了QT WIDGETS LIB 那么应用程序的对象就是QApplication 如果定义了QT GUI LIB 那么应用程序的对象就是QGuiApplication 否则 应用程序的对象就是QCoreApplication 如果使用
  • 入门机器学习(西瓜书+南瓜书)贝叶斯分类器总结(python代码实现)

    入门机器学习 西瓜书 南瓜书 贝叶斯分类器总结 python代码实现 一 贝叶斯分类器 1 1 通俗理解 先来看两个公式 P A B P
  • redis的五种数据类型详细图解

    众所周知 redis有五种数据类型 string 字符串 lists 列表 sets 无序的字符串集合 zsets 有序的字符串集合 hashs 哈希类型 一 string 字符串类型 在Redis中字符串类型的Value最多可以容纳的数据
  • vue 列表自动滚动到制定位置

    背景 业务开发中遇到一个需求 是要求跳转到新页面 并默认选中内容 如果内容在列表的位置靠后 就需要滚动到可见范围内 实现 1 循环实现列表 为每个item添加id id item index 方便后续查找对应项 div class item
  • Python作业(实验一)

    目录 1 输入一个日期 包括年 月和日 计算该日期是这一年的第几天 2 输入三个整数 把这三个整数按从大到小的顺序输出 3 分别用while语句和for语句编写程序 计算整数100到1000的和 4 随机生成两个1000到10000之间的整
  • HttpCanary使用指南——静态注入器

    HttpCanary更多资料 点我 静态注入器是HttpCanary最强大的功能之一 可以实现对Http请求数据和响应数据的拦截修改 静态注入器需要先选定一个请求 然后对其进行预编辑 编辑完成后便可对后续的相同请求进行自动修改 比如App发
  • 第二章 开始学习C++

    1 C 代码基本结构 以下是仿照C 在Microsoft Visual C 敲击的代码 对于新入门的我来说 能从中间学到一个完整的C 程序框架 test cpp 此文件包含 main 函数 程序执行将在此处开始并结束 include
  • linux服务器登录慢,报“/usr/bin/xauth: timeout in locking authority file /home/idriver-slave/.Xauthority”

    linux服务器登录慢 报 usr bin xauth timeout in locking authority file home idriver slave Xauthority 解决方法 1 查看用户目录的权限 cd home ll
  • 执行ipconfig -renew命令时出错: 系统找不到指定的文件?

    一位同事的戴尔台式电脑上不了网 执行 ipconfig renew时提示 在释放接口 Loopback Pseudo Interface 1 时出错 系统找不到指定的文件 操作失败 没有适配器处于允许此操作的状态 解决办法就是修复Winso
  • C#串口通讯中 16进制与字符串、字节数组之间的转换

    1 c 中如何将十进制数的字符串转化成十六进制数的字符串 十进制转二进制 Console WriteLine 十进制166的二进制表示 Convert ToString 166 2 十进制转八进制 Console WriteLine 十进制
  • 多linux系统u盘制作,如何制作一个通用的多系统安装U盘六(Linux相关配置)

    linux相关配置 要引导安装linux 需要把相关linuxISO文件中的相关文件复制出来 主要是核心文件 vmlinuz 和初始内存盘 initrd img 以及isolinux cfg配置文件 有以下区别 CentOS5 x RHEL
  • Addressables学习笔记

    文章目录 运行环境 资源引用 AssetReference 属性 AssetReferenceT AssetLabelReference AsyncOperationHandle 属性 Addressables API Instantiat