揭开AssetBundle庐山真面目(一)(二)

转载自侑虎科技UWA:

https://blog.uwa4d.com/archives/ABtopic_1.html

https://blog.uwa4d.com/archives/ABtopic_2.html

侑虎科技的技术贴子都很不错,建议大家去看看,创始人-张鑫 也是很牛的,斗鱼有开过公开课



AssetBundle 打包(4.x)基础

基本介绍

(1)常用打包API

public static bool BuildAssetBundle(Object mainAsset, Object[] assets, 
string pathName, out uint crc, BuildAssetBundleOptions assetBundleOptions,
BuildTarget targetPlatform);
public static string BuildStreamedSceneAssetBundle(string[] levels, 
string locationPath, BuildTarget target, out uint crc, BuildOptions options);
  • BuildPipeline.BuildAssetBundle
    对除Scene以外的资源打包,支持单个和多个;
  • BuildPipeline.BuildStreamedSceneAssetBundle
    对Scene文件打包,也支持单个和多个。

(2)常用打包选项(BuildAssetBundleOptions)

  • CompleteAssets
    用于保证资源的完备性。比如,当你仅打包一个Mesh资源并开启了该选项时,引擎会将Mesh资源和相关GameObject一起打入AssetBundle文件中;
  • CollectDependencies
    用于收集资源的依赖项。比如,当你打包一个Prefab并开启了该选项时,引擎会将该Prefab用到的所有资源和Component全部打入AssetBundle文件中;
  • DeterministicAssetBundle
    用于为资源维护固定ID,以便进行资源的热更新。

以上选项均已在5.x新机制中默认开启。因此在4.x版本中,开发者如果没有深入了解每个选项的意义,我们建议也都开启。

三个选项开启的情况下打包,可以保证在加载并实例化其中的Prefab时不会出现资源引用丢失的情况,因为所有依赖的资源都在包中。这也意味着,如果Prefab-A和Prefab-B引用了同一个Asset-A且分别打包时,两个包中就都会包含Asset-A。

UWA Tech Doc

加载到内存后,通过Profiler会发现Asset-A的冗余资源。

UWA Tech Doc

然而很多时候,并不希望把两个Prefab打在一个Bundle中,此时,就需要通过依赖性打包来解决。

依赖性打包

依赖性打包的作用在于避免资源冗余,同时提高资源加载和卸载的灵活性,其重要性不言而喻。在4.x版本的AssetBundle打包系统中,涉及一对 BuildPipeline.PushAssetDependencies和BuildPipeline.PopAssetDependencies接口,从官方文档中可以大致了解其用法:http://docs.unity3d.com/ScriptReference/BuildPipeline.PushAssetDependencies.html

你可以简单地认为,PushAssetDependencies是将资源进栈,PopAssetDependencies是让资源出栈,每打一个包,引擎都会检查当前栈中所有的依赖项,查看是否有相同资源已经在栈中。如有,则与其相关的AssetBundle建立依赖关系。机制不难理解,但使用中依然有几个容易忽视的注意点,请移步下文进阶篇。


AssetBundle 打包(4.x)进阶

注意点

  • 进行一次Push,多次Build操作,如依次Build资源Prefab-A,Prefab-B时,可以认为Prefab-A,Prefab-B会依次 进栈,所以如果两者之间也存在共享资源,则后者会依赖前者。具体表现为,运行时先加载Prefab-B会出现共享资源丢失的情况。

UWA Tech Doc

  • 4.x 中脚本也会作为“共享资源”参与依赖性打包,即当Prefab-A和Prefab-B同时挂有脚本M时,如果出现了上一点中的情况,那么后者同样会依赖前者。具体表现为,运行时先加载Prefab-B会出现脚本M丢失。

UWA Tech Doc

  • 将shader放入GraphicsSettings->Always Included Shaders中后,打包时会将相应的shader抽离,运行时加载时会自动加载其依赖的shader。同时也意味着,如果修改了Always Included Shaders或在一个新建项目中使用该Bundle,会出现shader丢失的问题。
  • 当需要更新bundle内容,但不改变依赖关系时,仍然需要重打其依赖的Bundle包。即如果Bundle-B依赖Bundle-A,那么在更新Bundle-A时可以不需要重打Bundle-B(前提是开启了DeterministicAssetBundle);但要更新Bundle-B的话,则必须重打Bundle-A。

AssetBundle打包(5.x)基础

基本介绍

(1)唯一API

public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions      assetBundleOptions = BuildAssetBundleOptions.None,BuildTarget targetPlatform = BuildTarget.WebPlayer);

调用BuildPipeline.BuildAssetBundles,引擎将自动根据资源的assetbundleName属性(以下简称abName)批量打包,自动建立Bundle以及资源之间的依赖关系。

(2)打包规则

在资源的Inpector界面最下方可设置一个abName,每个abName(包含路径)对应一个Bundle,即abName相同的资源会打在一个Bundle中。如果所依赖的资源设置了不同的abName,则会与之建立依赖关系,避免出现冗余。

UWA Tech Doc

支持增量式发布,即在资源内容改变并重新打包时,会自动跳过内容未变的Bundle。因此,相比4.x,会极大地缩短更新Bundle的时间。

(3) 新打包选项

除了前文提到的,5.x下默认开启的三个选项(CompleteAssets ,用于保证资源的完备性;CollectDependencies,用于收集资源的依赖项;DeterministicAssetBundle,用于为资源维护固定ID)之外,5.x中新增了以下选项:

  • ForceRebuildAssetBundle
    用于强制重打所有AssetBundle文件;
  • IgnoreTypeTreeChanges
    用于判断AssetBundle更新时,是否忽略TypeTree的变化;
  • AppendHashToAssetBundleName
    用于将Hash值添加在AssetBundle文件名之后,开启这个选项,可以直接通过文件名来判断哪些Bundle的内容进行了更新(4.x下普遍需要通过比较二进制等方法来判断,但在某些情况下即使内容不变重新打包,Bundle的二进制也会变化)。

与4.x不同的是,对于移动平台,5.x下默认会将TypeTree信息写入AssetBundle,因此在移动平台上DisableWriteTypeTree选项也变得有意义了。

(4)Manifest文件

在4.x版本中,我们通常需要自行维护配置文件,以记录AssetBundle之间的依赖关系,并供运行时使用。而在5.x版本中,Manifest文件可以免去这一过程。

(5) Variant参数

Variant参数能够让AssetBundle方便地进行“多分辨率支持”,相关详解请移步下文。


AssetBundle 打包(5.x)进阶

在新系统中,添加了以下两个实用的新特性,也许能够给开发者带来事半功倍的效果。

(1) Manifest文件

在打包后生成的文件夹中,每个Bundle都会对应一个manifest文件,记录了Bundle的一些信息,但这类manifest只在增量式打包时才用到;同时,根目录下还会生成一个同名manifest文件及其对应的Bundle文件,通过该Bundle可以在运行时得到一个AssetbundleManifest对象,而所有的Bundle以及各自依赖的Bundle都可以通过该对象提供的接口进行获取。

(2) Variant参数

在资源的Inspector界面最下方,除了可以指定abName,在其后方还可以指定Variant。打包时,Variant会作为后缀添加在Bundle名字之后。相同abName,不同variant的Bundle中,资源必须是一一对应的,且他们在Bundle中的ID也是相同的,从而可以起到相互替换的作用。

UWA Tech Doc

当需要为手机和平板上的某个UI界面使用两套分辨率不同的纹理、Shader,以及文字提示时,借助Variant的特性,只需创建两个文件夹,分别放置两套不同的资源,且资源名一一对应,然后给两个文件夹设置相同的abName和不同的variant,再给UI界面设置abName,然后进行打包即可。运行时,先选择合适的依赖包加载,那么后续加载UI界面时,会根据已加载的依赖包,呈现出相对应的版本。

开发者注意事项

  • abName可通过脚本进行设置和清除,也可以通过构造一个AssetBundleBuild数组来打包。
  • 新机制打包无法指定Assetbundle.mainAsset,因此无法再通过mainAsset来直接获取资源。
  • 开启DisableWriteTypeTree可能造成AssetBundle对Unity版本的兼容问题,但会使Bundle更小,同时也会略微提高加载速度。
  • Prefab之间不会建立依赖,即如果Prefab-A和Prefab-B引用了同一张纹理,而他们设置了不同的abName,而共享的纹理并未设置abName,那么Prefab-A和Prefab-B可视为分别打包,各自Bundle中都包含共享的纹理。因此在使用UGUI,开启Sprite Packer时,由于Atlas无法标记abName,在设置UI界面Prefab的abName时就需要注意这个问题。

UWA Tech Doc

  • 5.x中加入了Shader stripping功能,在打包时,默认情况下会根据当前场景的Lightmap及Fog设置对资源中的Shader进行代码剥离。这意味着,如果在一个空场景下进行打包,则Bundle中的Shader会失去对Lightmap和Fog的支持,从而出现运行时Lightmap和Fog丢失的情况.而通过将Edit->Project Settings->Graphics下shader Stripping中的modes改为Manual,并勾选相应的mode即可避免这一问题。

UWA Tech Doc


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值