返回

ET资源加载

结构

  • ResourcesComponent【资源组件】(用于加载资源)

    • AssetsBundleLoaderAsync【异步加载AB包组件】
    • AssetsLoaderAsync【异步获取包内资源组件】
  • BundleHelper【包助手】

    • BundleDownloaderComponent【包下载组件】(用来对比web端的资源,比较md5,对比所需下载资源)
      • UnityWebRequestAsync【Web异步请求组件】(用于下载文件)
      • PathHelper【路径助手】(包含各种设备内部资源地址)
    • VersionConfig【版本配置】
    • MD5Helper【MD5助手】

热更资源下载

  1. 调用BundleHelper.DownloadBundle()

  2. Using一个BundleDownloaderComponent包下载组件

    • 执行包下载组件的StartAsync方法

      • Using一个UnityWebRequestAsyncUnityWeb异步请求组件,用于下载服务器上的版本配置文件
        • 调用GlobalConfigComponent全局配置组件的GetUrl方法加上配置地址,获取资源服务器中版本文件的地址
        • 调用Web异步请求组件的DownloadAsync方法开始异步下载服务器上版本文件
      • Using一个UnityWebRequestAsyncUnityWeb异步请求组件,用于下载本地的版本配置文件
        • 调用PathHelper内部地址助手的AppResPath4Web方法,获取程序本地的资源版本文件存放地址
        • 调用Web异步请求组件的DownloadAsync方法开始异步下载本地的版本文件
      • 删除新版本中不需要的资源文件
        • PathHelper.AppHotfixResPath获取到本地的热更资源存放路径,获取路径中的所有文件名
        • 将文件名和服务器的版本配置文件做对比,删除版本配置文件中不存在的资源文件
      • 对比MD5
        • 将本地文件的MD5和远程的配置文件中的MD5作比较,如果不一样,则保存该文件的名称和大小
    • 调用事件,启动加载热更资源界面UI。

      注意:该热更资源界面UI较为特殊,他是在热更资源和代码前启动的,所以无法热更。必然的存放位置和获取方式也比较特殊,该UI的预制体存放在Resources目录下,可以通过ResourcesHelper.Load()方法直接加载获取资源。

    • 执行包下载组件的DownloadAsync方法

      开启循环,Using一个UnityWebRequestAsyncUnityWeb异步请求组件,用于下载上一步MD5不一样的文件

  3. 调用ResourcesComponentLoadOneBundle方法同步加载AB包【StreamingAssets】(暂时还没搞清楚这个包是怎么打出来的)

  4. 从【StreamingAssets】包中获取【AssetBundleManifest】,并赋值给ResourcesComponent.AssetBundleManifestObject

同步加载资源

  1. LoadBundle
    • 先将传入的文件名转小写
    • 调用AssetBundleHelper.GetSortedDependencies获取该AB包的所有依赖包
      1. GetSortedDependencies
        • 调用CollectDependencies收集目标AB包的依赖
        • 通过包依赖个数对依赖包名进行排序
      2. CollectDependencies
        • 调用GetDependencies获取目标AB包的依赖
        • 将依赖包名和依赖个数保存到数组中
        • 然后查询依赖包是否还存在套娃依赖包,调用自身递归获取所有子依赖包。
        • 如果包没有子项依赖,则从依赖数组中去除
      3. GetDependencies
        • 检测缓存字典中是否有该包的依赖项记录,如果有直接返回该包的依赖
        • 检测是否开启异步调用宏
          • 否,通过编辑器方法 AssetDatabase.GetAssetBundleDependencies获取依赖
          • 是,通过ResourcesComponent.AssetBundleManifestObjectAB包清单对象的GetAllDependencies方法获取所有依赖
        • 将依赖保存到缓存字典中
    • 遍历AB的所有依赖,并调用LoadOneBundle加载单个AB包的内存中
  2. LoadOneBundle
    • 先从已加载的AB包字典中查找该AB包是否已经加载,已加载则返回,并增加其引用数量
    • 如果没开启异步调用宏
      1. 调用编辑器方法AssetDatabase.GetAssetPathsFromAssetBundle获取AB包名下所有资源路径
      2. 遍历资源路径,并转换成资源名
      3. 通过资源路径加载资源到内存中
      4. 添加AB包名、资源名、资源到AB包字典中
      5. 根据AB包名创建ABInfo,并保存到字典中
      6. 退出方法
    • 获取AB包
      1. 通过PathHelper.AppHotfixResPath获取热更资源路径
      2. 检测路径是否存在
        • 如果存在则加载AB包
        • 如果不存在,通过PathHelper.AppResPath获取本地资源路径,然后通过路径加载AB包
    • 如果资源不是场景资源包,加载AB包中的所有资源,遍历调用AddResource保存资源到字典中
    • 根据AB包名和AB包创建ABInfo,保存到字典中

异步加载资源

  1. LoadBundleAsync逻辑上和LoadBundle一样
  2. LoadOneBundleAsync
    • 先从已加载的AB包字典中查找该AB包是否已经加载,已加载则返回,并增加其引用数量
    • 如果没开启异步调用宏
      1. 调用编辑器方法AssetDatabase.GetAssetPathsFromAssetBundle获取AB包名下所有资源路径
      2. 遍历资源路径,并转换成资源名
      3. 通过资源路径加载资源到内存中
      4. 添加AB包名、资源名、资源到AB包字典中
      5. 根据AB包名创建ABInfo,并保存到字典中
      6. 退出方法
    • 获取AB包
      1. 通过PathHelper.AppHotfixResPath获取热更资源路径
      2. 检测路径是否存在
        • 如果不存在,通过PathHelper.AppResPath获取本地资源路径
      3. using一个AssetsBundleLoaderAsync异步加载AB包组件,调用其LoadAsync方法开始异步加载AB包
        • 内部创建一个等待任务ETTaskCompletionSource<AssetBundle>,并调用AssetBundle.LoadFromFileAsync(path)加载AB包
        • Update事件中检测异步加载是否完,加载完整则将加载完成的结果AssetBundleCreateRequest.assetBundle,通过任务返回给调用方法
    • 如果资源不是场景资源包,using一个AssetsLoaderAsync异步加载资源组件,在Awake方法中传入上一步获取到的AssetBundle,调用其LoadAllAssetsAsync方法开始异步加载包内资源
      • 内部创建一个等待任务ETTaskCompletionSource,并调用assetBundle.LoadAllAssetsAsync()加载AB包
      • Update事件中检测异步加载是否完,加载完整则将加载完成的结果AssetBundleRequest.allAssets,通过任务返回给调用方法
    • 根据AB包名和AB包创建ABInfo,保存到字典中

卸载资源

  1. UnloadBundle

    • 先将传入的文件名转小写
    • 调用AssetBundleHelper.GetSortedDependencies获取该AB包的所有依赖包(里面步骤和加载时步骤相同)
    • 遍历AB的所有依赖,并调用UnloadOneBundle卸载单个AB包
  2. UnloadOneBundle

    • 转小写
    • 从字典中获取该AB包的ABInfo,并减少其引用个数
    • 如果ABInfoRefCount引用个数小于或等于零,用其自生的Dispose方法
    • 方法内部会调用其引用的AB包的AssetBundle.Unload(true)方法,从内存中移除

BuildEditor

为Unity打包构建提供一些选项,这里挑几个重点讲解

  1. BuildEditor脚本中,主要功能用于编辑器UI的渲染显示,其打包功能由BuildHelper.Build方法完成
  2. 一个下拉选项框用于选择打包平台,PC、安卓、ios等
  3. 是否打包ExE,其功能和Unity中Build Settings的打包功能一样,会根据上一步选择的不同平台构建不同的平台包
  4. 打包版本中可以选择开发版和发布版,开发版实际上在和Build Settings面板中勾选特定选项后打包一样(开发构建、自动链接分析器、脚本调试)
  5. 是否将资源打进ExE,内部逻辑为在调用BuildPipeline.BuildAssetBundlesAB打包方法,且将最后的构建AB包方式作为参数,打出AB包后,将打出的AB包保存到Assets/StreamingAssets路径中,然后再构建平台包
  6. 无论如何,选择好平台后,点击开始打包,都会在项目根目录下的../Release里生成新的AB包,和版本控制文件
  7. ET原生的AB包构建方式并没有对包体依赖进行优化,需要手动增加构建AB包依赖关系处理脚本

注意:打包时并不会在本地目录中创建版本控制文件,所以需要开发者手动在Assets目录下创建StreamingAssets文件夹,并创建Version文件。如果该文件丢失,在游戏启动后查找加载本地配置文件时就会由于找不到路径而报错

ASYNC异步宏

在Unity中打上ASYNC异步宏后会模仿其他平台通过Web资源服务器获取热更资源,并保存到StreamingAssets文件夹中

  • 需要注意的是删除该文件夹中资源后再次更新会出现无法找到资源的情况,是因为没有将版本控制器里的MD5码修改,建议在删除所有资源后将Version文件中数据替换成如下

    {"Version":0,"TotalSize":0,"FileInfoDict":{}}
    
  • 与ASYNC异步宏的冲突问题,在打上异步宏后需要执行下CLR绑定

Licensed under CC BY-NC-SA 4.0
0