unity3d:YooAsset零冗余构建Assetbundle代码分析

news/2024/12/22 17:16:40/

BuildAssetInfo构建asset信息

1.每个收集器下asset会构建出BuildAssetInfo,这种asset是没有冗余,只有依赖列表
2.每个依赖asset会构建出BuildAssetInfo,会记录将要打入的bundle列表

依赖的Asset列表

这个asset依赖的其他asset列表,只对收集器资源有效

		/// <summary>/// 依赖的所有资源/// 注意:包括零依赖资源和冗余资源(资源包名无效)/// </summary>public List<BuildAssetInfo> AllDependAssetInfos { private set; get; }

列表信息从何来?
在创建收集器资源调用依赖

YooAsset.Editor.AssetBundleCollector.GetAllDependencies

private List<string> GetAllDependencies(string mainAssetPath)
{string[] depends = AssetDatabase.GetDependencies(mainAssetPath, true);List<string> result = new List<string>(depends.Length);foreach (string assetPath in depends){if (IsValidateAsset(assetPath, false)){// 注意:排除主资源对象if (assetPath != mainAssetPath)result.Add(assetPath);}}return result;
}

预计会被打入的Bundle列表

HashSet< string> _referenceBundleNames
在处理数据时,如果一个依赖asset会被打入多个bundle,在这里记录,则视为冗余asset
这个bundle列表如何得到?
在遍历收集器资源依赖资源时,依赖资源add主资源的Bundle名
在最后处理冗余时,如果列表数量>2,则依赖asset生成独立bundle

BuildBundleInfo构建bundle信息

一个bundle会包含多个asset

主asset列表

/// <summary>/// 参与构建的资源列表/// 注意:不包含零依赖资源和冗余资源/// </summary>public readonly List<BuildAssetInfo> AllMainAssets = new List<BuildAssetInfo>();

1.普通bundle包,里面只有收集器asset,不会包含依赖asset。在构建时unity自动收集依赖进入bundle
2.共享bundle包,里面只有依赖asset

依赖asset列表

每个BuildAssetInfo又会包含List< BuildAssetInfo> AllDependAssetInfos,依赖资源列表

CollectAssetInfo收集器的asset

CollectAssetInfo是记录asset需要打入的bundle,和这个asset依赖的asset列表

asset的依赖列表

/// <summary>/// 依赖的资源列表/// </summary>public List<string> DependAssets = new List<string>();

如何得到
在创建CreateCollectAssetInfo时
YooAsset.Editor.AssetBundleCollector.CreateCollectAssetInfo
YooAsset.Editor.AssetBundleCollector.GetAllDependencies
调用AssetDatabase.GetDependencies,得到依赖列表

收集器Package,Group关系

package 的收集器资源
YooAsset.Editor.AssetBundleCollectorPackage.GetAllCollectAssets
收集器组
YooAsset.Editor.AssetBundleCollectorGroup.GetAllCollectAssets
一个收集器
YooAsset.Editor.AssetBundleCollector.GetAllCollectAssets
一个收集器按照规则又会包N个Asset

获取打包收集的资源文件

YooAsset.Editor.AssetBundleCollector.GetAllCollectAssets
1.如果收集器是文件夹路径,遍历下面所有资源类型,每个单独生成CollectAssetInfo加入字典
2.如果收集器是资源路径,只把该路径生成CollectAssetInfo加入字典
3.可寻址冲突,分两种情况,同个收集器与不同收集器;是对于同一个收集器而言,asset名字冲突,例如同个收集器下多个文件夹存在同名asset。例如
在这里插入图片描述

同个收集器下,两个文件夹下都存在cube1.prefab,报错

System.Exception: The address is existed : Cube1 in collector : Assets/YooAsset/Samples/Space Shooter/GameRes/Effect 
AssetPath:Assets/YooAsset/Samples/Space Shooter/GameRes/Effect/Engines/Cube1.prefabAssets/YooAsset/Samples/Space Shooter/GameRes/Effect/Explosions/Cube1.prefab

不同收集器在最后打包也会判断可寻址是否重复

System.Exception: The address is existed : Cube1 in group : battle 
AssetPath:Assets/YooAsset/Samples/Space Shooter/GameRes/Effect/Engines/Cube1.prefabAssets/YooAsset/Samples/Space Shooter/GameRes/Entity/Cube1.prefab

两个收集器里都有Cube1
在这里插入图片描述

资源构建上下文BuildMapContext

决定哪些是asset对应的bundle
YooAsset.Editor.TaskGetBuildMap.CreateBuildMap

BuildBundleInfo字典

key为bundle的名字,路径/换成_,从assets开始
Dictionary<string, BuildBundleInfo> _bundleInfoDic
在这里插入图片描述

所有asset构建BuildAssetInfo字典

Dictionary<string, BuildAssetInfo> allBuildAssetInfoDic
key为资源路径,BuildAssetInfo为打包路径

包含收集器的资源,收集器资源的依赖列表

录入所有收集器收集的资源

遍历allCollectAssetInfos

// 4. 录入所有收集器收集的资源foreach (var collectAssetInfo in allCollectAssetInfos){					allBuildAssetInfoDic.Add(collectAssetInfo.AssetPath, buildAssetInfo);}

收集器下的asset 是不会存在打入多个bundle情况

录入所有收集资源的依赖资源

只对依赖资源有效
1.遍历每一个allCollectAssetInfos.DependAssets
2.如果依赖asset未进入allBuildAssetInfoDic,则创建一个新BuildAssetInfo,它的_referenceBundleNames增加一个为收集器资源信息CollectAssetInfo的bundle,即添加关联的资源包名称
3.如果依赖asset已经存在于allBuildAssetInfoDic,说明已经被一个bundleA依赖,再添加bundleB的信息,标记为冗余资源。HashSet< string> _referenceBundleNames,这是个哈希表,如果bundleA = bundleB,不会加入

// 5. 录入所有收集资源的依赖资源
foreach (var collectAssetInfo in allCollectAssetInfos)
{string collectAssetBundleName = collectAssetInfo.BundleName;foreach (var dependAssetPath in collectAssetInfo.DependAssets){if (allBuildAssetInfoDic.ContainsKey(dependAssetPath)){allBuildAssetInfoDic[dependAssetPath].AddBundleTags(collectAssetInfo.AssetTags);allBuildAssetInfoDic[dependAssetPath].AddReferenceBundleName(collectAssetBundleName);}else{var buildAssetInfo = new BuildAssetInfo(dependAssetPath);buildAssetInfo.AddBundleTags(collectAssetInfo.AssetTags);buildAssetInfo.AddReferenceBundleName(collectAssetBundleName);allBuildAssetInfoDic.Add(dependAssetPath, buildAssetInfo);}}
}

填充所有收集资源的依赖列表

收集资源的依赖List< BuildAssetInfo>信息,只对收集资源有效,即这个收集资源的BuildAssetInfo的依赖List< BuildAssetInfo>

计算共享冗余的bundle

计算共享包名

YooAsset.Editor.BuildAssetInfo.CalculateShareBundleName
1.如果这个资源没有收集器类型CollectorType = ECollectorType.None,说明是被依赖的,非主动收集打包的
2.如果引用次数>1,说明至少被两个bundle引用,需要设置独立bundle,为了解决独立bundle过多的问题,按照资源的目录名字作为bundle名。如果同目录下还有零散资源被重复引用,都会打入这个包中。因为是按照零冗余ZeroRedundancySharedPackRule规则构建,生成的bundle名此asset的直接文件夹路径
3.如果引用 <= 1,只被一个bundle引用,不需要打独立bundle,把他bundle置为空

public void CalculateShareBundleName(ISharedPackRule sharedPackRule, bool uniqueBundleName, string packageName, string shadersBundleName){if (_referenceBundleNames.Count > 1){PackRuleResult packRuleResult = sharedPackRule.GetPackRuleResult(AssetPath);BundleName = packRuleResult.GetShareBundleName(packageName, uniqueBundleName);}else{// 注意:被引用次数小于1的资源不需要设置资源包名称BundleName = string.Empty;

AB依赖C,AB在同个Bundle

例如:Cube1,Cube2在同一bundleA里,它们都依赖MatCube.mat,那么MatCube.mat会被打入bundleA
在这里插入图片描述
在这里插入图片描述

AB依赖C,AB在不同Bundle

在这里插入图片描述

这种情况下C会打入共享包
在这里插入图片描述

bundle内容为空,因为被依赖asset不会通过代码加载

记录冗余资源

计算共享报名,已经去掉了冗余资源:把冗余asset的bundle变为文件夹路径名
如果asset有bundle名,一定不是冗余
对于没有bundle名的看,是否被2个引用

移除不参与构建的资源

如果一个asset的BuildAssetInfo.bundleName为空,说明它是被收集资源依赖的,且只被一个依赖,不需要生成一个独立bundle。这个asset会被打入依赖的bundle

构建资源列表

最后相当于遍历BuildAssetInfo字典,生成BuildBundleInfo字典
BuildAssetInfo字典 是N个重复的asset 对应bundle
BuildBundleInfo,是一个bundle里会有多少asset
最后按照bundle名生成BuildBundleInfo字典

构建

YooAsset.Editor.AssetBundleBuilder.Run
构建顺序,按照order来
在这里插入图片描述

两个比较重要的,TaskGetBuildMap 构建出零冗余的bundle关系:YooAsset.Editor.TaskGetBuildMap.CreateBuildMap

TaskBuilding:BuiltinBuildPipeline下出包

YooAsset.Editor.BuildMapContext.GetPipelineBuilds
根据BuildBundleInfo字典生成Ab信息
bundle里只插入主资源,依赖asset会 被收集插入bundle

		/// <summary>/// 获取构建管线里需要的数据/// </summary>public UnityEditor.AssetBundleBuild[] GetPipelineBuilds(){List<UnityEditor.AssetBundleBuild> builds = new List<UnityEditor.AssetBundleBuild>(_bundleInfoDic.Count);foreach (var bundleInfo in _bundleInfoDic.Values){if (bundleInfo.IsRawFile == false)builds.Add(bundleInfo.CreatePipelineBuild());}return builds.ToArray();}AssetBundleManifest buildResults = BuildPipeline.BuildAssetBundles(pipelineOutputDirectory, buildMapContext.GetPipelineBuilds(), buildOptions, buildParametersContext.Parameters.BuildTarget);

冗余MatCube.mat如何打包示例

asset:Assets/YooAsset/Samples/Space Shooter/GameRes/Material/MatCube.mat分配bundle:assets_yooasset_samples_space shooter_gameres_effect.bundle

asset:Assets/YooAsset/Samples/Space Shooter/GameRes/Material/MatCube.mat分配bundle:assets_yooasset_samples_space shooter_gameres_entity.bundle

发现bundle列表>1,重新分配bundle名
冗余:Assets/YooAsset/Samples/Space Shooter/GameRes/Material/MatCube.mat,分配bundleshare_assets_yooasset_samples_space shooter_gameres_material.bundle

生成BuildBundleInfo
bundleshare_assets_yooasset_samples_space shooter_gameres_material.bundle:塞入asset:Assets/YooAsset/Samples/Space Shooter/GameRes/Material/MatCube.mat

生成AB;bundle:share_assets_yooasset_samples_space shooter_gameres_material.bundle,assetNames;[“Assets/YooAsset/Samples/Space Shooter/GameRes/Material/MatCube.mat”]

报告bundleshare_assets_yooasset_samples_space shooter_gameres_material.bundle:里assets:[“Assets/YooAsset/Samples/Space Shooter/GameRes/Material/MatCube.mat”]


http://www.ppmy.cn/news/687773.html

相关文章

c++11 标准模板(STL)(std::basic_ostream)(三)

定义于头文件 <ostream> template< class CharT, class Traits std::char_traits<CharT> > class basic_ostream : virtual public std::basic_ios<CharT, Traits> 类模板 basic_ostream 提供字符流上的高层输出操作。受支持操作包含有格式…

Python多线程爬取7160网站美女图片

直接上代码 #codingUTF-8 from urllib.request import urlopen from pyquery import PyQuery as pq import re import pymongo import threading clientpymongo.MongoClient(hostlocalhost,port27017) tableclient.taobao.mutitry47160 lockthreading.Lock() i 1def save_to_…

做一个美女图片大全那种的网站怎么提高网站流量?

摘要&#xff1a; 大家都看到了美女图片大全网站流量是很巨大的&#xff0c;但是不知道怎么入手。其实&#xff0c;百度图库很多是收录来自各个网站里的图片的&#xff0c;你只要在你的网站做好图片&#xff0c;或者在高权重的网站里发布带有你网站图片的内容就比较容易了。 在…

python爬虫实践之爬取美女图片

目录 概述 准备 所需模块 涉及知识点 运行效果 完成爬虫 1. 分析网页 2. 爬虫代码 概述 爬取妹子图网的美女图片。 准备 所需模块 timerequestslxml 涉及知识点 python基础requests模块基础xpath表达式基础 运行效果 控制台打印&#xff1a; 电脑本地文件&…

Python3 大型网络爬虫实战 003 — scrapy 大型静态图片网站爬虫项目实战 — 实战:爬取 169美女图片网 高清图片

原博文链接&#xff1a;http://www.aobosir.com/blog/2016/12/26/python3-large-web-crawler-169bb-com-HD-beautiful-pictures/ 开发环境观察网页 和 网页源代码写程序 下载高清图片 下载 169美女图片网 的所有西洋美女的图片防反爬技术搞定 开发环境 Python第三方库&#x…

爬取福利,搞了一堆美女图片,代码奉上,多张福利

点赞再看,养成习惯 目录 展示成果: 分析网站 总结下: 技术分析 注:图片下载可运行

ModaHub ——向量数据库Milvus特征向量和预写式日志教程

目录 特征向量 什么是特征向量 特征向量的优势 应用领域 预写式日志 数据可靠性 缓冲区设置 旧日志删除 特征向量 什么是特征向量 向量是具有一定大小和方向的量&#xff0c;可以简单理解为一串数字的集合&#xff0c;就像一行多列的矩阵&#xff0c;比如&#xff1a…

【骚操作】Python 教你无损提取视频中的美女图片

前言 人类都是视觉动物&#xff0c;不管是男生还是女生看到漂亮的小姐姐、小哥哥就想截图保存下来。可是截图会对画质会产生损耗&#xff0c;截取的 画面不规整&#xff0c;像素不高等问题。 用 Python 写一个逐帧无损保存视频画面的小脚本大致可以分为三个步骤&#xff1a; …