返回

XAsset6.0入门

XAsset学习记录,仅供参考,持续更新

XAsset官网

当前版本:XAsset6.0首发版

目录说明

入门教程

官网入门教程

现在让我从零开始配置资源更新流程

打包配置

  1. 创建空项目,然后导入示例包。

  2. 导入后我们可以发现默认已经为我们创建了打包配置,我们需要将其删除

  3. 点击工具栏下的Groups,打开配置面板。

  4. 在窗口内右击,创建配置组。

  5. 创建成功后我们可以右击,进行重命名Preload。在配置组创建成功的同时,我们可以看到在工程目录下也生成了对应配置文件。

    1. 将我们需要打包的文件夹(UIVScenes)拖入窗口的组内,随后就会自动导入文件目录

    2. 点击窗口Build下拉菜单中的Groups,自动生成分组。生成成功后我们可以在窗口下看见多了一个Auto分组。

    3. 接下来点击Build下拉菜单的Budlis指令,生成资源包。

    4. 生成完成后点击工具栏下的BuildPath可直接跳转到我们的出包文件目录。

资源服务配置

  1. 下载hfs:https://www.rejetto.com/hfs/hfs.exe

  2. 打开hfs,将我们出包文件夹(unity项目下的Bundls文件夹,也是我们上步打包的输出目录),拖入到hfs中。

    会询问你要创建什么样的资源文件夹,我们选择Real folder(真实文件夹,非虚拟目录)。

  3. 创建完成后我们可以看见出现了一个服务网址,复制该网址到浏览器中打开,会出现如下界面(如果没有则说明你之前某一部操作有误)

运行

接下来我们来运行Demo

  1. 打开启动场景Startup,选择场景中的对象,在其Inspector面板中填入我们上一步生成的资源服务器地址。

    1. 运行游戏,之前操作都正常会进入如下界面(如果该步异常,请参考后面的异常解决方法)

      在Startup脚本中演示了异步加载该场景的代码

      三个场景示例如下:

      • LoadAsset:用于演示资源同步/异步加载、预制体实例化、资源卸载。【运行该场景先看后面常见问题的第二个问题】画面表现上会出现UI界面闪现后消失,是正常现象,因为演示代码的逻辑就是实例化资源两秒后销毁。
        • ManualUpdate:用于演示版本更新和手动更新游戏资源。运行过程可在log窗口看到更新日志输出。
      • AutoUpdate:用于演示版本更新,和单个资源自动更新和加载。

      三个场景运行的脚本都可以在工程目录的Example中找到。

常见问题

  1. 运行游戏报错找不到Menu_Sense的资源包。

    可能是已下载的资源出现丢失问题,点击工具栏下的View/DownloadPath ,跳转到当前本地下载的资源包目录,删除目录后的所有资源,重新加载游戏。

  2. 运行LoadAsset场景报错:找不到Components2_V2.prefab资源。

    这里需要我们新建一个配置组,然后将工程目录下Arts/Prefabs/UIC目录拖入,在配置组的inspector面板上勾选IncludeInBuild(这一步可以使unity在打包App时将该组的资源一起打入包体中),重新生成分组,再打包(运行Build下拉菜单的GroupBundles)。

  3. 非常重要一点,卸载Asset时不能使用.Unload()方法,而应该使用.Release()

功能说明

菜单栏功能说明

从上到下依次为:

  • Groups:显示组配置面板
  • Build:快捷打包,方便不用打开配置面板
    • Groups:快捷生成组
    • Bundles:快捷生成Bundles
    • Player:快捷发布App
  • Compute CRC:查看选中文件的冗余校验码(百度CRC)
  • View:快捷跳转一些目录
    • Settings:跳转到总配置文件
    • Build Path:打开资源打包目录
    • Download Path:打开编辑器下资源下载后保存的目录
    • Temporary:打开资源临时存放目录
  • Clear Progress Bar:清除进度条
  • Copy Path:拷贝当前在工程面板下选中对象的地址(例如:Assets/VEngine/Data/Groups/Auto.asset)

Groups分组编辑器

工具栏

  1. Create:创建组,有两种模式(Bundled和Raw,两种模式对比后续讲解)
  2. View:同菜单栏,用于跳转目录
  3. Refresh:刷新
  4. Simulation Mode:仿真模式,可以在编辑器下且未打包的情况下运行游戏
  5. 当前打包包体的大小

标题栏

  1. Path:当前分组的路径
  2. Size:当前分组所占包体总大小
  3. Label:单个文件的Bundle标签,相同标签的文件将打入同一个包 这里和Unity自带的打包标签不同,有待后续理解
  4. Bundle:打包后所属Bundle的名称
  5. Time:

分组配置

从上到下依次是:

  1. Bundle Mode:Bundle划分模式
    • Pack Together:分组中的除了场景外的所有资源按分组的名字一起打包,每个场景会按 分组名字 + 场景名字 进行打包。
    • PackByAssetName:资源按分组名字 + 源名字打包,子目录的资源会按一级资源的名字打包。
    • PackByLabel:同一个分组相同 label 的资源会打包到一起。
  2. Assets:所有打包的文件(文件夹)
  3. Include In Build:勾选该选项后,该分组的资源会在Unity发布资源时一起发布到包体中
  4. Size:大小
  5. Read Only:资源只读?

  1. Target:资源目标
  2. Label:资源标签
  3. Bundles:
  4. Dependencies:当前对象的相关依赖
  5. Time:时间
  6. Read Only:只读
  7. Children:包含的子对象
  8. Path:路径
  9. Root Path:根目录
  10. Parent Group:所属分组
  11. Auto:自动分组?

版本配置文件

从上到下依次是:

  1. Build Number:打包版本
  2. Assets:同上
  3. Budles:版本中所有的Budles
  4. Budles To Build:版本中所有变更的Budles
  5. Groups:版本中的所有分组
  6. Build Asset Bundle Options:资源包构建选项
  7. Simulation Mode:是否开启仿真模式,对应了Groups窗口中的Simulation Mode按键
  8. Startup Scene:启动场景,用于快捷发布App时指定启动场景
  9. Time Format:分组编辑器中的时间显示格式
  10. Size:上次打包的资源大小

  1. Assets:对应了单个分组的Assets设置信息
  2. Name:资源名
  3. Name With Aooend Hash:哈希名
  4. Size
  5. Crc:冗余校验码
  6. Time:

版本文件概要

在了解加载机制之前,先聊聊Bundle的版本控制文件manifest。他的内部构造见下图。

manifest文件在打包时会生成两个,一个在Unity发布成包的时候打入包体的StreamingAssets目录(StreamingAssets是只读的),用于取代了Unity的Resources目录功能(所以不管什么文件都不要用Resources加载),第二个在Build的时候放入服务器资源下载目录。

在框架启动时,会先用UnityWebRequest将文件manifest包体目录(StreamingAssets)中加载出来,重命名为manifestInBuild后保存到资源下载目录中。所以manifestInBuild会一直维持为Unity发布成安装包时的版本。

(需要注意的是,在编辑器下这一理论不正确,因为编辑器下会从Build的发布路径获取manifest文件,而不是从包体目录(StreamingAssets)中,这意味,版本文件永远是最新的。但一切以发包后为主,需要的可以发布后再进行测试)

在调用Versions.UpdateAsync方法后(版本更新Demo‘ManualUpdate和AutoUpdate都有用到),会将服务器下载目录下的manifest文件更新到下载目录下,名称不变。(不调用,是不会更新资源的)

每次新发布版本,Build后会将新版本的manifest文件自动更新到服务器下载目录中

所以,一个修改项目后正确的修改姿势应该如下:

  1. 点击Build下拉菜单的Bundles按钮。

  2. 在客户端执行Versions.UpdateAsync方法——运行Secen:ManualUpdateAutoUpdate

  3. 再加载资源——运行LoadAsset场景。

    (如果没有调用Versions.UpdateAsync而直接加载资源,将导致你的资源停留再上个版本)

流程解析

初始化流程

  1. 场景中挂载了Startup组件,在其Start方法内调用了Versions.InitializeAsync()
  2. Versions.InitializeAsync()New了一个InitializeVersions对象,并调用了它的Start方法,最后将InitializeVersions对象返还给第一步的Startup组件,用于监听初始化状态
  3. InitializeVersionsStart方法中做了两件事
    • 创建了一个挂在有Updater组件的Unity对象,该对象主要作用是用update方法驱动后面一系列下载与加载方法的委托(包括自身的Update方法,也间接性由其驱动)

    • 使用UnityWebRequest,在Update方法的驱动下下载版本清单文件manifestInBuild

      manifest文件在打包时会生成两个,一个在Unity发布成包的时候打入包体的StreamingAssets目录(这里取代了Unity的Resources目录),第二个在Build的时候放入资源目录。 下面的manifestInBuild就是从包体目录下读取出来然后写入资源下载目录的,因为StreamingAssets是只读的,且只能用WWW加载。 另外资源下载目录下还有一个manifest文件,该文件是在版本更新的时候从资源服务器下载的。

  4. 在下载完成后会调用OnComplete方法,对文件内容进行解析,把资源依赖和地址内容加载到内存中。最后调用Finish方法,这使最开始的Startup组件监听携程不再阻塞。

场景加载流程

Startup调用

  1. 在完成初始化后,接下来第一个实际作用演示——加载场景就来了Scene.LoadAsync()
  2. LoadAsync中创建了一个Scene(构造参数传入要加载的Scene路径),并调用SceneLoad方法(实际指向OnLoad方法)

Scene调用

  1. SceneOnLoad方法中创建Dependencies(构造方法中传入通过传入的加载路径解析到的AssetInfo信息),并调用其Load方法(实际指向OnLoad方法)。
  2. 在Update中监听Dependencies对象的加载状态是否完成,完成后调用SceneManager.UnloadSceneAsync加载场景。

Dependencies调用

  1. 通过AssetInfo创建一个BundleInfo,再调用Bundle.LoadInternal方法加载Bundle并返回一个Bundle对象,将Bundle添加到Bundle列表中,由OnUpdate方法维护

    在这一步中会调用Versions.GetBundlePathOrURL来获取地址,GetBundlePathOrURL会先对本地资源和最新资源文件记录的版本进行对比(失败返回服务器下载地址),然后从包体目录中查找(成功返回StreamingAssets地址),最后从本地已下载资源目录查找该文件,如果文件不存在,就返回服务器下载地址(带http)。

    Bundle对象是它的子类,根据返回地址是否带Http而选择的加载模式不同,所选子类也不同,在该按理加载过程中为DownloadBundle(不带Http即为本地加载LocalBundle)。

    创建后调用其Load方法(实际指向OnLoad方法)

  2. 重复上一步加载AssetInfo中的对应Bundle和所有引用Bundle

  3. OnUpdate中,检查Bundle列表中所有Bundle是否都加载完毕,如果是则改变自身加载状态,为加载完毕。

DownloadBundle调用

  1. 调用Download.DownloadAsync方法开始下载文件返回Download对象,并添加下载完成调用的回调方法OnDownloaded
  2. OnDownloaded方法中将下载对象进行解析,构建成AB包,并设置Versions中的资源路径
  3. Update方法中,监听Download对象的下载进度

Download静态调用

  1. 创建DownloadInfo对象,并调用DownloadAsync方法下载文件
  2. DownloadAsync创建下载对象Download,放入下载队列中,通过Update方法维护。
  3. UpdateDownloads方法中调用下载对象DownloadStart方法下载文件,并监听下载进度统计下载带宽。

Download调用

  1. Start方法中创建一个新线程,调用Run方法
  2. 在Run方法中先调用Downloading方法下载文件,然后调用CheckStatus方法校验下载文件正确性
  3. Downloading方法中使用HttpWebResponse创建下载请求下载数据流,写入到文件中

LoadAsset

异步加载

  1. LoadAssetStart方法中调用Asset.LoadAsync方法,传入加载路径和加载对象类型

    异步加载资源底层支持从服务器下载最新资源

  2. LoadAsync方法中调用LoadInternal方法,指定非同步加载

  3. LoadInternal方法中先根据路径从缓存中查找Asset资源添加到队列中,如果没有找到则创建BundledAsset,并调用其Load方法(实际指向OnLoad方法)

  4. Update方法中自动监听Asset对象是否被引用,如果没有引用则调用对象的Unload方法

BundledAsset调用

  1. OnLoad方法中创建Dependencies对象,并调用其Load方法(实际指向OnLoad方法)。后续跳转场景加载流程中的Dependencies调用

  2. Update方法中监听Dependencies对象的加载依赖是否完成,如果完成则开始异步加载AB包请求。

    在AB包加载请求完成后设置设置Asset为自身Asset

同步加载

  1. LoadAssetStart方法中调用Asset.Load方法,传入加载路径和加载对象类型

    同步加载不支持从服务器直接下载资源

  2. Load方法中调用LoadInternal方法,指定同步加载

  3. LoadInternal方法中先根据路径从缓存中查找Asset资源添加到队列中,如果没有找到则创建BundledAsset,并调用其Load方法(实际指向OnLoad方法)。

    而后调用BundledAssetLoadImmediate方法

BundledAsset调用

  1. OnLoad方法中创建Dependencies对象,并调用其Load方法(实际指向OnLoad方法)。后续跳转场景加载流程中的Dependencies调用

  2. Update方法中监听Dependencies对象的加载依赖是否完成,如果完成则开始异步加载AB包请求。

    在AB包加载请求完成后设置设置Asset为自身Asset

  3. LoadImmediate直接加载方法会检测Dependencies方法是否加载完毕,如果没有加载完成则调用DependenciesLoadImmediate方法

Dependencies调用

  1. OnLoad调用和异步加载相同。
  2. LoadImmediate方法会调用所有由OnLoad创建的Bundle(LocalBundle)对象的LoadImmediate方法

LocalBundle调用

  1. OnLoad方法会直接调用AssetBundle.LoadFromFileAsync方法加载本地AB包,将返回的请求保存到本地
  2. LoadImmediate方法会将请求中的Asset保存到本地,并调用加载结束方法。

异步实例化

优势:大量对象并行异步加载的处理,可以更平滑

  1. LoadAssetStart方法中调用InstantiateObject.InstantiateAsync方法,传入加载路径。
  2. InstantiateAsync方法中调用Start方法
  3. 接下来在Start方法中调用了Asset.LoadAsync(内部调用可直接跳转异步加载)
  4. 最后在Update方法中监听是否加载完毕,加载完毕后调用Object.Instantiate实例化对象

ManualUpdate

  1. ManualUpdateStart方法中调用Versions.UpdateAsync方法更新版本

    UpdateAsync方法中创建了UpdateVersions对象,并调用其Start方法

  2. 接下载会调用Versions.CheckAsync方法,对资源进行版本检验和更新,返回CheckVersions对象

    CheckAsync方法中,会创建CheckVersions对象并调用其Start方法

  3. 检查上一步CheckVersions对象中的下载队列是否存在文件,如果存在调用Versions.DownloadAsync方法对文件进行下载

UpdateVersions调用

  1. UpdateVersionsStart中会先对version文件进行下载,然后下载manifest文件

CheckVersions调用

  1. Start方法中会调用Versions.Manifest.GetBundlesWithGroups方法对所需要检查的分组名进行解析,并获取对应的所有BundleInfo存入列表
  2. Update方法中,会对列表中Bundle版本号和最新资源文件中的版本号进行对比,提取需要更新的资源并创建DownloadInfo存入队列中。

AutoUpdate

  1. AutoUpdate的Start方法中调用Versions.UpdateAsync方法更新版本,与ManualUpdate中第一步相同
  2. 调用LoadAsync加载资源,并在完成回调中实例化资源对象。与ManualUpdate不同,这里不再调用CheckVersions来对所有资源进行校验和更新。在加载过程中直接进行了版本对比和覆盖更新。

设计理念

Licensed under CC BY-NC-SA 4.0
0