使用 Addressables 来管理资源

一、安装

打开Package Manager,在Unity Technologies的目录下找到Addressables,更新或下载。

二、配置

依次打开Windows/Asset Management/Addressables/Groups菜单。

首次打开后会提示需要创建配置文件,点击Create Addressables Settings。

Assets目录下会生成AddressableAssetsData文件夹。

Ⅰ. 认识资源组(AssetGroups)与组策略(AssetGroups Schemas)概念

  1. 点击Manage Groups,返回刚才的Addressables Groups面板。此时已经有了两个内置的组。

  2. Built In Data存储的是工程中Resources文件夹下的资源,随App构建的场景资源,以及其他一些必要的资源等。

  3. Default Local Group (Default)组存储的是工程中被标记为Addressables的资源,假如不对其进行手动分组,则默认放在这个组中。

  4. 点击Create,可以指定模板来复制一个组或者创建一个全新的组。模板存储在AddressableAssetsData/AssetGroupTemplates文件夹下,默认有一个名为Packed Assets的模板,新创建的组存储在AddressableAssetsData/AssetGroups文件夹下。我们手动建立一个名为Remote的新组。

  5. 点击Remote组的Add Schema按钮,添加Content Update Restriction和Content Packing & Loading策略。注意不要额外添加Resources and Built In Scene策略,这个已经由Built In Data组负责了。

    在AssetGroups文件夹中有一个Schemas文件夹,存放着所有资源组的组策略序列化文件,命名规则为$"{组名}_{策略类型}"。

  6. 配置Remote组策略。

    • 修改在Content Update Restriction下的Update Restriction选项。

      Can Change Post Release的意思是,当前资源组进行最终构建时会完全覆盖上一次构建结果(打包出的文件名与上一次不同,上一次的包彻底无效化,部署时可以直接删掉),一般这种方式叫做 全量更新

      而Can not Change Post Release则意味着,当前资源组构建时需要与上一次构建结果进行比对(Addressables Groups/Tools/Check for Content Update Restrictions),上一次构建出的包不发生变化,新构建的包则建立在旧包的基础上(相同的资源存储在旧包内,修改和添加的资源存储在新包内,部署时需要将新包和旧包一起发到服务器上),这种方式一般叫做 增量更新。

    • 修改Content Packing & Loading下的Build Path和Load Path选项。

      • LocalBuildPath 本地构建路径,当App发布时,会将这个路径下的包拷贝到App的StreamingAssets里。

      • LocalLoadPath 本地加载路径,当App运行时,会从这个路径下读取资源包,一般也是在App的StreamingAssets里。

        Local___Path 说明这个组中的资源包会包含在App的安装包内。如果所有资源组都设置为Local,则这个App安装包是 全资源包 (全资源包一般是设置为Can not Change Post Release的)。

      • RemoteBuildPath 远程构建路径,当构建资源包后,需要将这个路径下的包拷贝到服务器上。

      • RemoteLoadPath 远程加载路径,当App运行时,会从这个地址下载catalog,并与本地catalog对比来判断是否需要更新资源。

      如果想对 全资源包 进行更新,可以点击Addressables Groups/Tools/Check for Content Update Restrictions,会自动生成差异化资源组,将这些资源组设置为远程并构建部署,则可以将App内包含的旧资源进行覆盖。

    • Advanced Options 是更精细化控制资源包构建与加载流程的选项,无特殊情况保持默认即可。需要注意的是Include in Build选项,可以控制当前资源包是否参与本次构建。

Ⅱ. 总体配置

AddressableAssetSettings负责整体配置资源包的构建参数。

设置资源包地址的Profiles

Profiles/Profiles In Use 控制了当前资源包路径设置。

我们刚才对资源包的路径进行了本地与远程的设置,但是并没有深入了解这些路径是如何拼接而成的。比如为什么本地资源包会在构建到StreamingAssets文件夹中呢。

点击Manage Profiles,弹出上图的Addressables Profiles面板,之前我们设置的本地路径与远程路径就是在这里定义的。总体上路径由固定的字符串、中括号与花括号组成,中括号内包含了发布时编辑器所确定下来的变量,比如运行平台等;花括号则包含了App运行时所获取的变量,也可以在代码内手动指定一个自定义的变量。

这就解释了为什么我们将资源包指定为Local___Path时,最终会存在于App的StreamingAssets文件夹中,是因为[UnityEngine.AddressableAssets.Addressables.BuildPath]这个地址就是编辑器发布App时所指定目录下的StreamingAssets文件夹地址,而{UnityEngine.AddressableAssets.Addressables.RuntimePath}这个地址则是App运行时的StreamingAssets文件夹地址。

我们也可以新建一个测试用的Profile和一个发布用的Profile,只需要把RemoteLoadPath中的http地址指向测试用服务器地址和正式版服务器地址即可。

设置是否需要远程更新

假如我们的App不需要进行远程资源加载和更新,则保持Content Updata/Build Remote Catalog不勾选即可,否则则需要将其勾选。

而Disable Catalog Update on Startup则决定是否在App启动时自动更新catalog。

假如我们希望App启动时将所有的更新包先行下载下来,则可以将其勾选,并在代码中手动调用
Addressables.InitializeAsync()、
Addressables.CheckForCatalogUpdates()、
Addressables.UpdateCatalogs()
等方法,获取到需要更新的资源包列表,并对其依次进行手动更新。

假如我们希望在App运行中需要某个资源时才会去从远程下载,则可以保持其不勾选的默认状态。这种方式下Addressables系统会在App启动时自动调用上述的一系列方法将本地catalog与远程同步,但是并不会更新资源包。

三、资源管理

  1. 将资源导入工程中

  2. 此时Inspector面板上新添加了一个Addressable选项。

    将需要打包的资源勾选,出现一长串的资源路径,这个路径就是我们加载这个资源时所需要的路径参数

  3. 点击Select按钮,弹出资源组面板,刚添加的资源会位于默认组员组Default Local Group (Default)中。

  4. 如果能保证不冲突的话,我们也可以将这个路径手动简化,或者让编辑器自动对其进行简化。在资源组面板右键资源并点击Simplify Addressable Names,可以将复杂的路径简化为不带类型后缀的文件名,方便使用。

  5. 也可以为资源指定标签。将一系列资源指定为同一个标签后,则可以在App运行时将其以按标签加载的方式同时加载进来。比如我们将工程中的Lua脚本全部指定一个Scripts的标签等。

四、构建资源包

Ⅰ. 首次构建

首次构建资源包需要点击资源组面板的Build/New Build/Default Build Script。

打包成功后在AddressableAssetsData文件夹下生成一个保存当前资源状态的bin文件,这个文件是后续资源增删改时用来与前一次打包做对比用的,并且它保存了至关重要的catalog文件信息。

同时在RemoteBuildPath位置生成catalog以及远程资源包。

此时我们可以随即进行App的构建。

每次构建资源包,都需要重新构建App。

如果希望更新资源包,不能使用Build/New Build方式。

Ⅱ. 更新包

将资源增删改完毕之后,点击Tools/Check for Content Update Restrictions。

选择首次构建时生成的bin文件,弹出Content Update Preview面板,点击Apply Changes。

我们这里的默认资源组的Content Update Restriction选项设置的是Can not Change Post Release,因为本地资源已经跟随App一同发布了,修改本地资源是没有意义的,除非重新构建App。

编辑器替我们自动生成了新的远程资源组,并将有变动的资源放了进去。

这里不要混淆 远程资源组 和 Content Update Restriction 两个概念,远程资源组既可以标记为不可修改,也可以标记为可修改。

我们可以把这些资源放到其他远程组里,也可以保持不变,这方面的策略应该顾及资源包的粒度,文件大小等,严格执行起来还是比较烧脑的。

资源组重新设定完毕后,点击Build/Update a Previous Build,并再次选择首次构建时生成的bin文件,以更新方式构建资源包。

切勿以Build/New Build的方式构建,如果不小心点了,两个解决方式,git reset --hard或者重新打包App……

此时打开远程构建目录(RemoteBuildPath),发现已经生成了由新的远程资源组构建的资源包,而catalog文件的修改日期也已经发生了变化,说明虽然catalog文件名没有发生变化,但是其内容已经更新了。

我这里截图的catalog文件名发生了变化,是写文测试的时候把之前的构建结果给删了,实际上应该是不会发生变化的,请忽略。o_0

我们允许的流程是:构建资源包->构建App->以更新方式构建资源包->以更新方式构建资源包...

我们不允许的流程是:...->构建App->构建资源包...

原因是每次点击Build/New Build/***,catalog文件名都会发生变化,而App只记录上一次构建资源包时的catalog文件名,假如我们在构建App之后重新构建了资源包,则旧的App无法识别新的catalog,从而更新失败。

五、部署

将RemoteBuildPath目录下的文件上传至服务器,包括资源包以及catalog文件,保证RemoteLoadPath可访问即可。

实际部署还是比教程写的要麻烦很多的。权限,跨域,负载能力,加密,防止各种网络攻击等,各种手段都要用上。我们仅仅是验证技术路线,麻烦事就先不考虑啦。

如果仅仅是测试的话,其实编辑器还提供了一个Host功能

点击Create/LocalHosting,新建一个服务端,指定端口,勾选Enable即可。

注意我们需要将Profiles/RemoteLoadPath修改为http://本机IP或者localhost:端口号,默认Profiles的远程加载地址多了一个[BuildTarget],这是访问不到的。

六、加载

新建一个脚本,用来测试资源的加载。

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI; public class SwitchSprites : MonoBehaviour
{
[SerializeField] private RawImage _emojiImage;
[SerializeField] private Text _infoText; private int _indicator; private AsyncOperationHandle<IList<Texture>> _operation; private async void Start()
{
_operation = Addressables.LoadAssetsAsync<Texture>("emoji", null);
await _operation.Task; _infoText.text = "Emoji Load Completed"; GetComponent<Button>().onClick.AddListener(() =>
{
_indicator++;
if (_indicator >= _operation.Result.Count)
{
_indicator = 0;
} _emojiImage.texture = _operation.Result[_indicator];
});
} private void OnDestroy()
{
Addressables.Release(_operation);
}
}

这里一上来直接就可以Addressables.LoadAssetsAsync<Texture>(),是因为我测试的时候没有勾选AddressableAssetSettings/Content Update /Disable Catalog Update on Startup,所以App在加载时自动更新了catalog,而资源包下载则类似于Lazy 模式,即用即下载(缓存中如果有匹配的资源包则直接加载)。真正使用这套系统时,一般会采用勤快一点的模式,先更新必要的资源包,读条一波,然后App才正式运行。

使用 Addressables 来管理资源的更多相关文章

  1. 基于EasyUI Treegrid的权限管理资源列表

    1. 前言 最近在开发系统权限管理相关的功能,主要包含用户管理,资源管理,角色管理,组类别管理等小的模块.之前的Web开发中也用过jQueryEasyUI插件,感觉这款插件简单易用,上手很快.以前用到 ...

  2. EC笔记:第三部分:13、以对象管理资源

    C++相比Java等含有gc的语言来说,内存管理方面(也包括资源管理)比较令人头疼.一些初级程序员,甚至是一些经验丰富的老程序员,也会经常在资源管理上犯错.这时候就需要一个能够自动管理资源的东西(gc ...

  3. spring security动态管理资源结合自定义登录页面

    如果想将动态管理资源与自定义登录页面一起使用,最简单的办法就是在数据库中将登录页面对应的权限设置为IS_AUTHENTICATED_ANONYMOUSLY. 因此在数据库中添加一条资源信息. INSE ...

  4. Effective C++ ----以对象管理资源

    以对象管理资源 通过对象的析构函数的自动调用来自动释放资源 第一部分:几种典型的以对象管理资源的例子 1. STL::auto_ptr 获取资源后立刻放入资源管理对象 std::auto_ptr< ...

  5. [Effective C++ --013]以对象管理资源

    这一节基本讲述的是将资源放进管理对象,防止忘记释放资源. 1.一般New和Delete使用场景 void fun() { SimpleClass* pSimpleClass1 = new Simple ...

  6. 《Effective C++》学习笔记条款13 以对象管理资源

    条款 13 :以对象管理资源 例:      voidf()      {           Investment *pInv = createInvestment();           ... ...

  7. 以对象管理资源——C++智能指针auto_ptr简介

    auto_ptr是C++标准库提供的类模板,它可以帮助程序员自动管理用new表达式动态分配的单个对象.auto_ptr对象被初始化为指向由new表达式创建的对象,当auto_ptr对象的生命期结束时, ...

  8. 第十九章——使用资源调控器管理资源(1)——使用SQLServer Management Studio 配置资源调控器

    原文:第十九章--使用资源调控器管理资源(1)--使用SQLServer Management Studio 配置资源调控器 本系列包含: 1. 使用SQLServer Management Stud ...

  9. 第十九章——使用资源调控器管理资源(2)——使用T-SQL配置资源调控器

    原文:第十九章--使用资源调控器管理资源(2)--使用T-SQL配置资源调控器 前言: 在前一章已经演示了如何使用SSMS来配置资源调控器.但是作为DBA,总有需要写脚本的时候,因为它可以重用及扩展. ...

随机推荐

  1. Jmeter二次开发实现自定义functions函数(九)

    在Jmeter->选项->函数助手对话框中我们可以看到Jmeter内置的一些常用函数,但考虑到测试过程中的实际情况,我们经常需要在脚本引用或者实现自定义的函数.那么如何在"函数助 ...

  2. 组件通过props属性传值

    组件之间的传值 组件是一个单独功能模块的封装,有属于自己的data和methods,一个组件的 data 选项必须是一个函数 为什么必须是函数:因为只有当data是函数时,不同实例调用同一个组件时才会 ...

  3. Redis这15个“雷坑”,别问我咋知道的……

    来源:https://dbaplus.cn/news-158-3836-1.html

  4. vuex4 极速入门到上手

    vuex4 是 vue3的兼容版本,提供了和vuex3 的相同API.因此我们可以在 vue3 中复用之前已存在的 vuex 代码. 一.安装以及初始化 vuex4安装: npm install vu ...

  5. 基于EPPlus和NPOI实现的Excel导入导出

    基于EPPlus和NPOI实现的Excel导入导出 CollapseNav.Net.Tool.Excel(NuGet地址) 太长不看 导入 excel 文件流将会转为 ExcelTestDto 类型的 ...

  6. js 开始

    hello world 开始JavaScript 是一种脚本语言,它的解释器被称为 JavaScript 引擎.JavaScript 被发明用于在 HTML 网页上使用,给HTML网页增加动态功能.J ...

  7. 菜鸡的Java笔记 第二十八 - java 包的定义

    包的主要作用以及定义    包的导入操作    系统常见的开发包    jar 程序命令        包的定义        在任何的操作系统之中都有一个统一的共识:同一个目录下不能够存在有相同的文 ...

  8. Android SeekBar 自定义thumb,thumb旋转动画效果

    简介 某些音乐播放或者视频播放的界面上,资源还在加载时,进度条的原点(thumb)会显示一个转圈的效果. 资源加载完成后,又切换回静态效果.这个效果增强了用户体验. 一般来说有美术人员负责设计和切图. ...

  9. [luogu4607]反回文串

    参考ARC064F 令$h(n)=\begin{cases}n(n为奇数)\\\frac{n}{2}(n为偶数)\end{cases}$,$f(n)$定义与ARC064F相同,答案即$\sum_{d| ...

  10. C语言下的Led灯

    1. 设计思想 1.1 设置处理器模式 设置sp啥的汇编要先进入SVC模式,超级管理员特权模式,这样就可以访问所有寄存器了,需要用到cpsr寄存器 0到4位要设置svc模式10011 = 0x13, ...