UGF资源更新与管理
https://www.jianshu.com/p/80bff8c9004a
打包配置
ResourceBuilder.xml文件保存了打包配置信息
参数:
InternalResourceVersion:内部版本号
Platforms:生成的ab资源所对应平台编号,二进制左移,与或非运算得到
AssetBundleCompression:压缩格式标号,不压缩,LZ4压缩,LZMA压缩
CompressionHelperTypeName:压缩解压缩辅助器类型名称
AdditionalCompressionSelected:是否进行再压缩以降低传输开销
ForceRebuildAssetBundleSelected:是否强制重新构建 AssetBundle
BuildEventHandlerTypeName:构建ab的相关事件类类型名称
OutputDirectory:ab输出文件夹,其他输出目录根据该目录派生
OutputPackageSelected:是否生成package资源
OutputFullSelected:是否生成full资源
OutputPackedSelected:是否生成Packed资源
各个目录解释说明:
Working: Unity 生成 AssetBundle 时的工作目录。
Package: 为单机模式生成的文件的所在目录,若游戏是单机游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后构建 App 即可。
Full: 为可更新模式生成的完整文件包的所在目录,若游戏是网络游戏,生成结束后应将此目录上传至资源服务器,供玩家下载用。
Packed: 为可更新模式生成的文件的所在目录,若游戏是网络游戏,生成结束后将此目录中对应平台的文件拷贝至 StreamingAssets 后构建 App 即可。一个 AssetBundle 是否会生成到 Output Packed Path,取决与这个 AssetBundle 是否在 AssetBundle 编辑工具中被标记为 Packed。(此目录下存储的是随APP一起发布的资源)
BuildReport: AB包和非AB包文件,在GF中被统一抽象为 Resource 文件,文件后缀为.dat ,在我们的资源列表中,记录的即是这些 .dat 资源文件的资源信息,信息中包含了这些资源文件的名称,hashcode,长度,zipHashcode,zip长度,是否AB包,加载设置,等等信息。
打包流程
打包的流程执行过程从按下Start Build Resources按钮开始
找到ResourceBuilder脚本,当点下按钮bool类型变量m_OrderBuildResources值变为true时,开始执行BuildResources()方法
private void Update()
{
if (m_OrderBuildResources)
{
m_OrderBuildResources = false;
BuildResources();
}
}
类关系
类的创建关系如下
ResourceBuilder:资源生成器(入口)
ResourceBuilderController:资源构建控制器
ResourceAnalyzerController:资源分析控制器
ResourceCollection:资源集合
Resource:ab包所含资源信息
Asset :资源文件信息
//资源生成器(入口)
ResourceBuilder : EditorWindow
{
private ResourceBuilderController m_Controller = null;
}
//资源构建控制器
ResourceBuilderController
{
ab包所含的资源文件数量127
private readonly ResourceCollection m_ResourceCollection;
private readonly ResourceAnalyzerController m_ResourceAnalyzerController;
//ab资源全路径-ab包信息键值对,ab包的数量116
private readonly SortedDictionary<string, ResourceData> m_ResourceDatas;
}
//资源分析控制器
ResourceAnalyzerController
{
private readonly ResourceCollection m_ResourceCollection;
//每个资源文件所依赖的资源
private readonly Dictionary<string, DependencyData> m_DependencyDatas;
//每个被依赖的资源(a)所对应的依赖它的资源(b,c)所形成的列表,(b,c)属于ab包里的资源
private readonly Dictionary<string, List> m_ScatteredAssets;
//ab资源和散资源综合后的所有依赖关系列表
private readonly List<string[]> m_CircularDependencyDatas;
//依赖关系资源列表(ab+分散),无序集合,查找快速,不会重复
private readonly HashSet m_AnalyzedStamps;
}
//资源集合
ResourceCollection
{
//ab路径-ab资源Resource信息键值对(116)
private readonly SortedDictionary<string, Resource> m_Resources;
//guid-Assets键值对(127)
private readonly SortedDictionary<string, Asset> m_Assets;
}
//ab包所含资源信息
Resource
{
private readonly List m_Assets;//ab包所含资源文件
private readonly List m_ResourceGroups;//所属资源分组
public string Name //ab包名
public string Variant //变体名称
public string FullName //全名,含路径
public AssetType AssetType //资源类型,资源or场景
public bool IsLoadFromBinary //是否从二进制文件加载
public string FileSystem
public LoadType LoadType //资源加载方式类型
public bool Packed //是否是主包资源
}
//资源文件信息
Asset : IComparable
{
public string Guid;//资源文件guid
public string Name;//资源文件名
public Resource Resource;//所属ab包
}
//依赖数据信息
public sealed class DependencyData
{
//所依赖的ab包
private List m_DependencyResources;
//所依赖的ab包内的文件
private List m_DependencyAssets;
//所依赖的散文件名称
private List m_ScatteredDependencyAssetNames;
}
//依赖关系信息
//每个资源文件可能有多个依赖的文件,ab包里的资源文件有多少个依赖关系,就有多少个该结构
struct Stamp
{
private readonly string m_HostAssetName;//资源文件名
private readonly string m_DependencyAssetName;//被依赖的资源文件名
}
入口是ResourceBuilderController.BuildResources()方法,主要流程如下:
1、创建文件系统
生成各个模式的ab资源文件夹
2、设置ab资源生成选项
BuildAssetBundleOptions buildAssetBundleOptions = GetBuildAssetBundleOptions();
3、收集资源信息
m_ResourceCollection.Load()
读取资源信息xml文件(Assets/GameMain/Configs/ResourceCollection.xml)
从ResourceCollection.xml文件获取需要打包的资源信息填充到ResourceCollection类的m_Resources和m_Assets,ResourceCollection类由ResourceBuilderController创建
4、分析依赖资源
分析
m_ResourceAnalyzerController.Analyze();
ResourceAnalyzerController类由ResourceBuilderController创建。ResourceAnalyzerController的m_ResourceCollection资源数据来源于ResourceBuilderController。
该步骤主要填充ResourceAnalyzerController的属性信息m_DependencyDatas
List<string[]> m_CircularDependencyDatas= new List<string[]>();
m_CircularDependencyDatas[0]=new string[]{a,b,d,c,b}
m_CircularDependencyDatas[1]=new string[]{b,d,c,b}
m_CircularDependencyDatas[2]=new string[]{c,b,d,c}
m_CircularDependencyDatas[3]=new string[]{e,f,h,e}
m_CircularDependencyDatas[4]=new string[]{f,h,e,f}
m_CircularDependencyDatas[5]=new string[]{h,e,f,h}
如果只有a,e在ab包里面,那么其他所有依赖的b,c,d,f,h,k则也进行统计
5、准备构建ab资源的数据
PrepareBuildData(out assetBundleBuildDatas, out assetBundleResourceDatas, out binaryResourceDatas)
注意,只有assetBundleBuildDatas是编辑器导出AssetsBundle需要的数据,数据从ResourceBuilderController.m_ResourceCollection获取,并不直接依赖于上一步对资源进行的分析,而分析资源所产生的数据为了更直观的显示在分析器面板。也就是说分析的结果并没有对资源进行处理,这一步可以
6、为选定的平台构建资源
BuildResources(Platform.Windows, assetBundleBuildDatas, buildAssetBundleOptions, assetBundleResourceDatas, binaryResourceDatas);
构建资源分为三步
1、生成资源文件及资源及资源列表文件(即以生成路径命名的文件,Windows和Windows.manifest)
AssetBundleManifest assetBundleManifest = BuildPipeline.BuildAssetBundles(workingPath, assetBundleBuildDatas, buildAssetBundleOptions, GetBuildTarget(platform));
利用assetBundleBuildDatas数据生成ab资源,在working目录下
[图片]
2、输出加密的ab包及字节流检验码
关键函数如下,自行查找
ProcessAssetBundle(platform, workingPath, outputPackagePath, outputFullPath, outputPackedPath, AdditionalCompressionSelected, assetBundleResourceDatas[i].Name, assetBundleResourceDatas[i].Variant, assetBundleResourceDatas[i].FileSystem)
ProcessOutput(platform, outputPackagePath, outputFullPath, outputPackedPath, additionalCompressionSelected, name, variant, fileSystem, resourceData, bytes, length, hashCode, compressedLength, compressedHashCode)
3、输出各个平台下加密的列表文件
ProcessPackageVersionList(outputPackagePath, platform);
ProcessReadOnlyVersionList(outputPackedPath, platform);
ab资源加载
DefaultLoadResourceAgentHelper
///
/// 通过加载资源代理辅助器开始异步读取资源文件。
///
/// 要加载资源的完整路径名。
public override void ReadFile(string fullPath)
{
if (m_LoadResourceAgentHelperReadFileCompleteEventHandler == null || m_LoadResourceAgentHelperUpdateEventHandler == null || m_LoadResourceAgentHelperErrorEventHandler == null)
{
Log.Fatal(“Load resource agent helper handler is invalid.”);
return;
}
m_FileFullPath = fullPath;
//将本地资源加载到内存
m_FileAssetBundleCreateRequest = AssetBundle.LoadFromFileAsync(fullPath);
}
ab构建分析
学习完源码后受益颇深,ab构建中对资源的分析很完整,资源更新使用了增量更新,不用开发人员去关注更新了哪些内容以及资源内容的记录单独打包,及其友好。
资源分析完成后,在项目对资源管理不完善的情况下我们可能会面临两个问题。
每个ab包所依赖的同一个散文件会多次复制打包进每个ab包,是否可以考虑分析界面提供指导如何分类打包,重复通用的散资源单独打包,减少资源的冗余。
据说yooasset、MotionFramework框架对于冗余处理的很好,有待继续学习研究,此处放上链接。
https://zhuanlan.zhihu.com/p/615830582