Unity Addressables资源管理系统
文章目录
- Addressable Asset System(可寻址资产系统)
- 1. 背景
- 2. Addressable系统介绍
- 3. Addressable系统优势:
- 4. Addressable系统与AssetBundle的区别
- Addressable系统的使用
- 1. 安装
- 2. Addressables管理窗口
- 3. AddressableAssetSettings系统设置
- 4. 资源组设置
- 5. 标记资源
- 6. 资源打包
- 7. 加载资源
- 8. 更新资源包
- 9. 热更新代码和方案
- 10. 资源自动分组
- 11. 内存管理
- 12. Addressable打包粒度
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,在发布后,允许修改,更新时做覆盖更新。
- Update Restriciton:
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不够强大,而是这是跟具体项目有关,每个项目的情况各不相同。
Unity Addressables资源管理系统相关推荐
- Addressable Asset System(进阶版AB)和AssetBundle(以下简称AB)制作的资源管理系统的对比
介绍 AB作为之前Unity主推的资源管理工作流,可以把模型.贴图.预制体.声音.甚至整个场景都打入压缩包中,然后在游戏过程中再加载.使用他的主要目的有以下几点:1.统一的资源管理.2.做分包.3.热 ...
- [Unity workflows] Unity Addressables 教程:学习基础知识
英文原文:https://thegamedev.guru/unity-addressables/tutorial-learn-the-basics/ 欢迎来到这个 Unity Addressables ...
- Mesos:一个开源的分布式弹性资源管理系统
2019独角兽企业重金招聘Python工程师标准>>> Mesos是一个开源的资源管理系统,可以对集群中的资源做弹性管理. Mesos是高仿google内部的资源管理系统borg实现 ...
- 可视化排班管理_企业人事资源管理系统
经过市场调研和分析,发现部分企业的人力资源管理在绩效考核.信息传递和任务管理方面存在一些问题.为企业开发的人力资源管理系统的重点是利用现代高效的运作方式,开发和管理组织中比较昂贵的资源,实现人力资源管 ...
- web端项目管理/工程项目劳务资源管理系统/考勤审批/人员招聘/企业管理系统/工资管理/入职管理/组织结构/财务管理/大数据指挥中心/劳务系统/岗位工种/智慧工程监管/劳务app原型/axure原型
web端项目管理/工程项目劳务资源管理系统/考勤审批/人员招聘/企业管理系统/大数据智慧中心/工资管理/入职管理/组织结构/财务管理/大数据指挥中心/劳务系统/岗位工种/axure原型/rp原型 Ax ...
- 一个资源管理系统的设计--基于cgroup机制
设计一个资源管理系统对于一个综合性的资源访问系统来说是十分必要的,而好的设计一定是不复杂的,甚至说是十分简单的,原因就是精简机构,消除冗余,或者说精兵简政在任何时候任何方面总是必要的,我们不希望管理机 ...
- 通过Mixamo生成人物动画并导入Unity实现资源可用的方法
通过Mixamo生成人物动画并导入Unity实现资源可用的方法: 文章要点: 如何通过Mixamo生成人物动画 在Mixamo中生成的模型及动画导入Unity的设置(保持原有材质) 在Unity中利用 ...
- 货拉拉 Android 动态资源管理系统原理与实践(上)
点击上方蓝字关注我,知识会给你力量 ❝ jary,货拉拉高级客户端工程师,目前负责货拉拉App Android端稳定性提升,包体积优化相关工作. ❞ 前言 随着公司业务的扩展,货拉拉用户端apk包的体 ...
- 北大青鸟资源管理系统
S1总复习(6)北大青鸟管理系统 目录 S1总复习(6)北大青鸟管理系统 数据库操作 主窗口 界面 代码 添加窗口 界面 代码 查询窗口 界面 代码 数据库操作 添加几条数据 主窗口 界面 代码 us ...
最新文章
- 详解PHP实现定时任务的五种方法
- UI培训教程分享:UI设计如何确定设计风格
- 移动端制作公共样式reset
- 摄像头自动曝光_OPPO新专利曝光:手写笔不仅仅只是手写笔 它还是手机的额头...
- ajax请求的完整步骤
- 视频播放页php,html jquery简易视频播放器
- 关于 equals 和 hashCode,看这一篇真的够了!
- FE.ENV-manjaro虚拟机配置和常见前端工具安装
- Java黑皮书课后题第8章:8.18(打乱行)编写一个方法,使用下面的方法头打乱一个二维int型数组的行。编写一个测试程序,打乱下面的矩阵
- 严格模式explainFetchTask
- mysql 并发_mysql 的读写锁与并发控制
- linux安装软件imagemagick,Linux系统中怎么安装和使用ImageMagick软件?
- 文件打包,下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
- 大一c语言上机题库及详解答案,二级C语言上机题答案(题库答案).doc
- CAD工程制图软件中洁具图库的使用
- 当KPI说谎:数据科学错误的高昂代价
- 关于编译优化选项o3的问题
- mysql替换后的zzigu_MySQL导入数据报错Got a packet bigger than‘max_allowed_packet’bytes错误的解决方法...
- 123457123457#0#-----com.cym.shuXueWangGuo1--前拼后广--儿童数学
- 学生搭配问题数据结构报告c语言,数据结构课设学生搭配问题