IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> Unity Addressables资源管理系统 -> 正文阅读

[游戏开发]Unity Addressables资源管理系统

Addressable Asset System(可寻址资产系统)

1. 背景

??在开始介绍Addressable系统之前,我们先来回顾下传统的几种资源加载方式:

  • 直接引用: 使用直接引用是最简单快捷的,但不可动态加载。
  • Resources资源管理: Resources文件夹下所有文件都会打包到安装包,无论资源是否被使用,这样就会导致包体过大;Resources没办法做热更新资源;Resources加载资源时,对资源路径要求严格。
  • AssetBundle资源管理: 可热更,但管理难度大。

2. Addressable系统介绍

??可寻址资产系统是Unity推出的新的资源管理插件。Addressable系统是在 Asset Bundle之上,提供了异步加载、依赖管理以及内存管理等丰富的资源管理功能,也能够让开发者实现远程资源更新更加的便捷。

3. Addressable系统优势:

  • 快速迭代:
    使用Addressable在开发前期就进入快速开发的阶段,无论使用任何你喜欢的资源管理技术,都能快速切换到Addressable系统中。几乎不需要修改代码。
  • 依赖管理:
    系统不仅返回请求内容,还返回该内容所有依赖项,以便在返回内容之前加载所有网格、着色器、动画等。
  • 内存管理:
    Addressable不仅仅能加载资源,同时也能卸载资源。
  • 内容打包:
    Addressable系统自动管理了所有复杂的依赖连接,所以即使资源移动了或是重新命名了,系统依然能够高效地找到准确的依赖进行打包。当你需要将打包的资源从本地移到服务器上面,Addressable系统也能轻松做到。 相较于传统的资产加载方式(Resources/AssetBundle),Addressable系统拥有了完备的可视化编辑窗口以及内存管理。

4. Addressable系统与AssetBundle的区别

  • Addressable系统只需要资产的地址就可以从任意位置加载,而AssetBundle需要从指定bundle包中加载资源。
  • Addressable系统使用引用计数自动管理内存卸载,而AssetBundle需要开发者手动管理。
  • Addressable系统自动管理依赖关系,而AssetBundle需要开发者自己管理依赖关系,维护起来比较困难。
  • 可寻址资源系统默认的所有加载操作都是异步操作,可以添加事件监听,而AssetBundle则有同步和异步加载。
    在这里插入图片描述

Addressable系统的使用

1. 安装

????Unity 2018.2及以上版本,使用PackageManager安装Addressables。
在这里插入图片描述

2. Addressables管理窗口

????Window > Asset Management > Addressables > Groups进入使用界面
在这里插入图片描述
Addressable设置:
????资源默认分为Built In Data和LocalGroup(Default)两组,前者包含一些内置资源,不能改动,后者可以进行添加或删除资源。

  • Create: 创建新的资源分组,也可以在Addressables Group窗口中右键 Create New Group > Packed Assets创建新的资源组。
  • Profile: Profile的作用主要是用于指定项目中需要用到的几个地址,我们可以在这个窗口中点击Create->Profile创建Profile,每个Profile中都包含4个默认的变量,我们也可以点击Create->Variable扩展变量。
  • Tools:
    • Profiles: 用于给整个Addressable设置范围(配置四种路径的具体值)之后可以给每个组的Build,Load选择路径种类,则根据Profile的选取确定。
    • Labels: 添加删除标签Label。
    • Analyze: Analyze是一个工具,收集有关您的项目的可寻址布局的信息。在某些情况下,Analyze可能会采取适当的措施来清理项目的状态。在其他情况下,Analyze纯粹是一种信息工具,使您可以对可寻址布局做出更明智的决策。在这里插入图片描述
    • Hosting Services: Addressables系统自带的一个资源服务,可以指定一个目录存放远程资源,然后通过连接这个服务器,来更新资源。
    • Event Viewer: 可以用于监测,调试。前提是在Inspect System Settings窗口勾选发送消息(由于消耗性能所以默认关闭)。
      ????使用Addressables事件查看器可监视所有Addressables系统操作的资源的引用计数。在Unity中选择Window > Asset Management > Event Viewer。
      ????请注意,事件查看器只关心引用计数,而不关心内存消耗。在"Asset"栏下列出每一帧中,可以看到每一个资源的如下信息:
      ????FPS: 每秒帧数。
      ????MonoHeap: 内存使用的总量。
      ????Event Counts: 每帧事件总数。
      在这里插入图片描述
      ????可以单击左箭头和右箭头逐帧观察,或者单击Current跳转到最新的帧。按+按钮展开一行以获得更多详细信息。
      ????事件查看器中显示的信息与在Play Mode Script中选择的游戏模式有关。 使用事件查看器时,应避免使用 Use Asset Database模式,因为它不考虑资产之间的任何依赖关系。使用Simulate Groups 或Use Existing Build模式,但是后者更适合于事件查看器,因为它可以更准确地监视资源的引用计数。
    • Check for Content Updata Restrictions: 更新静态资源组。
  • Play Mode Script:
    • Use Asset Database(fastest): 允许你在游戏流程中快速运行游戏。它直接通过Asset Database加载Asset ,这会在不需要分析器或assetBundle创建的情况下进行快速迭代。
    • Simulate Groups(advanced): 在不创建assetBundles的情况下分析布局和依赖项的内容。asset 通过ResourceManager从assetDataBase加载,就假装它们是通过包加载的一样。若要查看游戏期间bundles加载或卸载的时间,请在Addressables事件查看器窗口Tools > Event Viewer
    • Use Exiting Build(requires built groups): 最接近于已部署的应用程序生成,但它要求你将数据作为单独的步骤进行构建。如果不修改Asset,则此模式是最快的,因为它在进入Play模式时不处理任何数据。必须通过选择Build>New Build>Default Build Script,或者在游戏脚本中使用AddressableAssetSettings.BuildPlayerContent()方法,在Addressables组窗口(Window>Asset Management>Addressable>group>group)中构建此模式的内容。
  • Build:
    • New Build: 当所有资源都已准备就绪,点击此项打包。
    • Update a Previous Build: 资源更新时,点击此项更新资源包。
    • Clear Build: 清除已经Build的资源,再次运行游戏需要重新Build。

3. AddressableAssetSettings系统设置

在这里插入图片描述
Addressable系统的基础配置:

  • Disable Catalog Update On Startup: 默认是没有勾选的,没有勾选,那么每次AA系统初始化的时候,会自动更新catalog文件,勾选上,将不会自动更新catalog文件,也就意味着不会自动更新资源.AA系统的初始化会在任意接口第一次调用时初始化,也可以主动调用Addressables.InitializeAsync()初始化.
  • Build Remote Catalog: 默认没有勾选,只有勾选上才会创建catalog在指定目录,以后客户端才可以下载这个catalog来进行对比更新.
  • Build Path: 资源打包后存放的地址。
  • Load Path: 资源加载地址。
  • Send Profiler Events: 调试用,允许加载资源的时候发送事件给EventViewer,可以通过这个工具查看资源的使用情况
  • Log Runtime Exception: 输出加载资源时的异常,开启时如果资源加载发生异常,会直接抛出.如果关闭,我们也可以通过加载资源时返回的句柄,来获取到异常信息.同时我们也可以给项目添加宏ADDRESSABLES_LOG_ALL,来查看更多的日志信息

4. 资源组设置

在这里插入图片描述

  • Build Path: 资源打包后存放的地址。
  • Load Path: 资源加载地址。
  • Advanced Options(高级设置):
    • Asset Bundle Compression: 当前.bundle文件的压缩方式,支持LZ4和LZMA压缩。
    • Include in Build: 是否被打包,默认是勾选的,若不勾选当前组不打包。
    • Requset Timeout: 设置UnityWebRequest在超时的秒数超过后尝试中止。(仅适用于远程资源包)
    • Bundle Mode: 控制捆绑包的打包方式。PackTogether将一个分组打包成一个资源包;Pack Separately每一个资源打成一个包,Pack Together By Label将Lable相同资源打成一个资源包。
  • Content Update Restriction:
    • Update Restriciton:
      • Cannot Change Post Release: 静态Group,在发布后,无法被修改,只能通过Check for Content Updata Restrictions做增量更新,创建一个新的资源分组.
      • Can Change Post Release: 非静态Group,在发布后,允许修改,更新时做覆盖更新。

5. 标记资源

在这里插入图片描述
????这里有两种方式将资源标记成可寻址的,在安装好可寻址资源包后,你可以在属性面板进行标记或者将其拖拽到管理窗口指定分组上。在资源的属性窗口上,点击Address复选框并为资源设置唯一标识符。

注:如果我们标记的资产在Resources文件夹下时,Addressable系统会提示你讲资产移出Resources文件夹。
在这里插入图片描述

6. 资源打包

????配置好资源分组,根据需要设置Play Mode Script,再通过Build > New Build > Default Build Script打包测试。
????本地资源打包路径: Library/com.unity.addressables/StreamingAssetsCopy/aa/Android/
????远程资源打包路径: ServerData/Android/
在这里插入图片描述
????同时远程目录下会生成有.hash和.json文件,.hash文件内只包含一个catalog文件的Hash值,用于客户单检测catalog更新时,通过对比这个hash值,判断是否有catalog更新,json文件内包含每个Ab包的hash值和地址。
????使用Build > Update a previous Build 更新资源包时,需要选择一个bin文件(android环境为例,Anroid/.bin),这个bin文件记录了所有Ab包之间的依赖关系和分组信息,Addressable系统通过这个bin文件管理依赖。

7. 加载资源

????使用AssetReference加载资源:

[SerializeField] private AssetReference m_AssetReference; 
    private  void Start() { 
        m_AssetReference.LoadAssetAsync<GameObject>(); 
    }

????使用Addressables加载单个资源:

 private void OnResLoadAsset(string key) 
    { 
        Addressables.LoadAssetAsync<GameObject>(key).Completed += OnCompleteLoad;
    } 
    private void OnCompleteLoad(AsyncOperationHandle<GameObject> asyncOperationHandle) 
    { 
        GameObject go = GameObject.Instantiate(asyncOperationHandle.Result); 
    }
    private void OnResInstantiate(string key) 
    { 
        Addressables.InstantiateAsync(key); 
    }

???? 加载多个资源:

private void OnResLoadAsset(string key,string lable) 
    { 
        Addressables.LoadAssetsAsync<Texture2D>(new List<object> { key, lable }, null, 
            Addressables.MergeMode.Intersection).Completed += OnCompleteLoadAssets; 
    } 
    private void OnCompleteLoadAssets(AsyncOperationHandle<IList<Texture2D>> asyncOperationHandle) 
    { 
        //DebugTools.Log(asyncOperationHandle.Result.Count); 
    }

注:第三个参数,MergeMode查找资源的合并模式,以传入的参数是new List{key,label}为例

  • Node或UseFirst时,会取第一个key查询到的资源
  • Union时,取并集
  • Intersection时,取交集

小结:
(1)加载资源时,若加载资源指定的类型与资源类型不一致,Addressable系统找不到该资源,则抛出异常,无法加载资源,前提:系统设置勾选了Send Profiler Events。
(2)使用标签管理,同一个资源的地址和标签可以相同,当有多个资源标签相同,Addressable系统会返回第一个满足条件的资源。
(3)若资源的地址名称与下一个资源的标签相同,返回还是第一个资源,Addressable系统会对比资源的地址和标签,若都不相同,才会继续向下查找

8. 更新资源包

????热更新资源包修改后,需要对资源重新打包
????Check for Content Update Restrictions: 针对是静态资源组,既是Update Restriciton属性为Cannot Change Post Release值。点击后弹出选择之前打包资源组生成的bin文件,点击“Apply Changes”应用更改,增加或修改的资源会被移动到新建Content Update分组。在这里插入图片描述
????Update a Previous Build: 动态资源组更新时,执行该操作,同样需要选择bin文件,系统会自动生成一个新的AB包。
在这里插入图片描述

9. 热更新代码和方案

????核心代码

 public IEnumerator CheckForContentUpdate(List<object> keys)
 {
     for (int index = 0; index < keys.Count; index++)
     {
         AsyncOperationHandle<long> DownloadSize = Addressables.GetDownloadSizeAsync(keys[index]);
         yield return DownloadSize;
         if (DownloadSize.Result <= 0)
         {
             Debug.Log("[Addressable]:不需要更新的资源标签:" + keys[index]);
             keys.Remove(keys[index]);
         }
         else
         {
             m_TotalSize += DownloadSize.Result / Mathf.Pow(1024, 2);
         }
     }
     m_DownloadDependencies = Addressables.DownloadDependenciesAsync(keys, Addressables.MergeMode.Union, false);
     yield return m_DownloadDependencies;
}
  • 方案一:
    ????从服务器获取更新资源标签。

注:动态资源更新,旧资源会被覆盖,动态资源组中有一个资源需要更新,热更时会将整个资源组都下载下来
,因此合理划分资源分组十分重要,减少重复下载以及打包粒度(多个资源需要相同的材质、贴图等资源)。

  • 方案二:
    ????使用官方提供的Addressables.CheckForCatalogUpdates()方法检查目录,获取需要更新的目录。
  • 方案三:
    ????暴力获取所有Key,使用官方的Addressables.GetDownloadSizeAsync(Key)检查资源是否需要更新,从而获取需要更新的所有Key值。
    ????资源更新具体实现:
    ????????使用官方提供的Addressables.GetDownloadSizeAsync(Key)方法获取所有需要更新的资源地址或标签集合,再通过Addressables.DownloadDependenciesAsync(Key, Addressables.MergeMode.Union, false)下载更新的资源。

10. 资源自动分组

????项目中需要管理的资源过多时,勾选Addressable或拖拽的方式明显不在合适,因此需要实现一个方法,将某个文件夹下的所有资源标记为可寻址资源。
????编辑状态创建一个新的菜单,并创建一个asset文件,配置需要标记的资源文件夹,可同时标记多个资源,配置如下:
在这里插入图片描述

public static void AutoSetGroup(string groupName, string lableName, string assetPath, bool isSimplied = false) 
{ 
    var set = AddressableAssetSettingsDefaultObject.Settings; 
    AddressableAssetGroup Group = set.FindGroup(groupName); 
    if (Group == null) 
    { 
        Group = set.CreateGroup(groupName, false, false, false, new List<AddressableAssetGroupSchema> 
            { set.DefaultGroup.Schemas[0], set.DefaultGroup.Schemas[1]}, typeof(SchemaType)); 
    } 
    string Guid = AssetDatabase.AssetPathToGUID(assetPath);  //获取指定路径下资源的 GUID(全局唯一标识符)
    AddressableAssetEntry asset = set.CreateOrMoveEntry(Guid, Group); 
    if (isSimplied) 
    { 
         asset.address = Path.GetFileNameWithoutExtension(assetPath); 
    } 
    else 
    { 
         asset.address = assetPath; 
    } 
    asset.SetLabel(lableName, true, true); 
}

????具体思路:
????????根据文件夹路径,获取该文件夹下的所有资源的路径信息,调用添加分组接口,检查是否存在当前分组,若无,则创建AddressableAssetGroup类型分组对象,设置默认状态,使用AssetDatabase.AssetPathToGUID获取当前路径资源的GUID,通过AddressableAssetSettingsDefaultObject.Settings.CreateOrMoveEntry(),创建AddressableAssetEntry对象,既勾选了addressable,再去简化资源地址和设置标签。

11. 内存管理

资源加载
????Addressables.LoadAssetAsync();单个资源
????Addressables.LoadAssetsAsync();多个资源
????Addressables.LoadSceneAsync();场景的加载
????GamoeObject实例化加载
????Addressables.InstantiateAsync();实例化加载
????GameObject.Instantiate();Unity提供实例化方法
资源卸载
????Addressables.UnloadSceneAsync();场景的卸载
????Addressables.Release();释放资源,参数是资源或????AsyncOperationHandle句柄
????Addressables.ReleaseInstance();销毁Addressable系统创建的实例

注:Addressables.InstantiateAsync()和其他加载调用的另一个区别就是有一个可选的trackHandle参数,当设置为false时,就必须通过AsyncOperationHandle句柄来释放资源,而不能再通过AsyncOperationHandle.Result加载资源释放了。

引用计数问题: 资源卸载,可手动和自动。
????手动卸载,Addressable系统加载和卸载资源都是成对存在的,使用Addrsssables.Release()或Addressables.ReleaseInstance()方法卸载资源,减少引用计数。当资源的引用计数为0时,该资源就准备好卸载了,并减少了所有依赖项的引用计数。
????自动卸载,包含它的场景关闭时允许自动清理。
卸载问题
????若使用Addressables.ReleaseInstance()传入的实例并不是Addressables系统API创建的,或者是通过句柄创建实例,系统会检测到并返回false,以指示该方法无法释放指定的实例。在这种情况下,实例不会被销毁。
Addressables.LoadAsset()和Addressables.InstantiateAsync()讨论
????Addressables.InstantiateAsync()有一些相关的开销,所以如果需要在每一帧中实例化数百次相同的对象,可以考虑通过Addressables.LoadAsset()方法加载,然后通过GameObject.Instantiate()实例化。缺点是Addressables系统不知道您创建了多少实例,如果管理不当,可能会导致内存问题。例如,一个Prefab引用了一个加载不正确或者已经卸载的纹理,会导致渲染问题(或更糟)。这类问题很难跟踪,因为您可能不会立即触发内存卸载 。?
清除内存
????不再被引用的资源并不一定意味着资源产已被卸载。一个常见的应用场景涉及到一个资源包中包含多个资源。例如:
?????您有三个资源(“树”,“坦克”,“牛”)在同一个资源包(“东西”)。
?????当“树”加载时,“树”的ref-count +1,“东西”的ref-count +1。
?????稍后,当“坦克”加载时,“树”和“坦克”的ref-count均为1,并且“东西”包的ref-count为2。
?????如果你释放“树”,它的ref-count就会变成0。
????在这个例子中,“树”资源实际上并没有被卸载。您可以加载资源包或其部分内容,但不能部分卸载资源包。在包本身完全卸载之前,所有资产都不会卸载。这个规则的例外是Resources.UnloadUnusedAssets,在上述场景中执行此方法将导致树卸载。因为Addressables系统不能识别这些事件, 只反映Addressables的ref-counts (不完全反映内存中存在的内容)。注意,如果您选择使用Resources.UnloadUnusedAssets,这是一个非常慢的操作,应该只在一个不会显示任何游戏内容的屏幕调用(比如加载屏幕)。

12. Addressable打包粒度

????我们在使用Addressable系统时,需要考虑的是:需要多少个Group?这个Group里面放什么资源?打包方式是Pack Together 或者 Pack Together By Label 或者 Pack Separately? 很显然,这个跟使用Assetbundle是一样的,需要开发人员自己来规划。这不是因为Addressable不够强大,而是这是跟具体项目有关,每个项目的情况各不相同。

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-09-10 11:11:09  更:2021-09-10 11:11:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 15:05:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码