AssetBundle学习

官方文档:AssetBundle 工作流程 - Unity 手册 (unity3d.com)

之前写的博客:AssetBundle学习_zaizai1007的博客-CSDN博客

使用流程图:

  •  1,指定资源的AssetBundle属性     (xxxa/xxx)这里xxxa会生成目录,名字为xxx
  • 2,构建AssetBundle包
  • 3,上传AB包
  • 4,加载AB包和包里面的资源

BuildAssetBundleOptions

BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦它被下载了之后,它会使用LZ4算法保存到本地上。

BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,包大,加载快

BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。 注意使用LZ4压缩,可以获得可以跟不压缩想媲美的加载速度,而且比不压缩文件要小。

Asset Bundle 文件

Asset Bundle

  1. AssetBundle.LoadFromMemoryAsync
  2. AssetBundle.LoadFromFile
  3. WWW.LoadFromCacheOrDownload
  4. UnityWebRequest 

Loading Assets from AssetBundles 

//一般
T objectFromBundle = bundleObject.LoadAsset<T>(assetName);

//GameObject
GameObject gameObject = loadedAssetBundle.LoadAsset<GameObject>(assetName);

//所有资源
Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();

 加载Manifests文件可以处理资源的依赖

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = 
assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

//Pass the name of the bundle you want the dependencies for.
string[] dependencies = manifest.GetAllDependencies("assetBundle"); 
foreach(string dependency in dependencies)
{
    AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
}

 AssetBundle的卸载

卸载有两个方面

  1. 减少内存使用
  2. 有可能导致丢失

所以什么时候去卸载资源

AssetBundle.Unload(true)卸载所有资源,即使有资源被使用着     

  1. (在关卡切换、场景切换
  2. 资源没被用的时候 调用)

AssetBundle.Unload(false)卸载所有没用被使用的资源     

个别资源怎么卸载

  1. 通过 Resources.UnloadUnusedAssets.  
  2. 场景切换的时候    

以下文章参考:AssetBundle详解 - 知乎 (zhihu.com)

一:AssetBundle介绍

AssetBundle是将资源使用Unity提供的一种用于存储资源的压缩格式打包后的集合,它可以存储任何一种Unity可以识别的资源,如模型,纹理图,音频,场景等资源。也可以加载开发者自定义的二进制文件。他们的文件类型是.assetbundle/.unity3d,他们先前被设计好,很容易就下载到我们的游戏或者场景当中。

(1)创建Asset bundle,开发者在unity编辑器中通过脚本将所需要的资源打包成AssetBundle文件。

(2)上传服务器。开发者将打包好的AssetBundle文件上传至服务器中。使得游戏客户端能够获取当前的资源,进行游戏的更新。

(3)下载AssetBundle,首先将其下载到本地设备中,然后再通过AsstBudle的加载模块将资源加到游戏之中。

(4)加载,通过Unity提供的API可以加载资源里面包含的模型、纹理图、音频、动画、场景等来更新游戏客户端。

(5)卸载AssetBundle,卸载之后可以节省内存资源,并且要保证资源的正常更新。

2.2 打包AssetBundle

AssetBundle创建之后需要导出,这一个过程就需要编写相应的代码实现,从Unity5.x之后,提供了一套全新简单的API来实现打包功能。大大简化了开发者手动遍历资源自行打包的过程,更加方便快捷。需要在Asset目录下创建Editor目录,表示该脚本是对于编辑器的一个扩展。脚本写完之后,也不需要进行挂载,会自动在Unity的菜单栏中生成。单击子菜单,既可以进行打包AssetBundle。具体实现代码如下:

using UnityEditor;
public class ExportAssets : MonoBehaviour {

	[@MenuItem("Test/Build Asset Bundles")]
	static void BuildAssetBundles(){

BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
BuildAssetBundleOptions.UncompressedAssetBundle,BuildTarget.
StandaloneOSXUniversal);
	}
}

所有的AssetBundle已经被导出,此时每一个AssetBundle资源会有一个和文件相关的Mainfest 的文本类型的文件,该文件提供了所打包资源的CRC和资源依赖的信息。

除此之外,还有一个AssetBundle文件会在生成的时候被创建,记录者整个资源列表以及列表之间的关系。

资源卸载

资源卸载部分的变化不大,使用的仍然是Unload方法。

该方法会卸载运行时内存中包含在bundle中的所有资源。

当传入的参数为true,则不仅仅内存中的AssetBundle对象包含的资源会被销毁。根据这些资源实例化而来的游戏内的对象也会销毁。

当传入的参数为false,则仅仅销毁内存中的AssetBundle对象包含的资源。

六:AssetBundle依赖加载

如果一个或者多个 UnityEngine.Objects 引用了其他 AssetBundle 中的 UnityEngine.Object,那么 AssetBundle 之间就产生的依赖关系。相反,如果 UnityEngine.ObjectA 所引用的UnityEngine.ObjectB 不是其他 AssetBundle 中的,那么依赖就不会产生。

假若这样(指的是前面两个例子的后者,既不产生依赖的情况),被依赖对象(UnityEngine.ObjectB)将被拷贝进你创建的 AssetBundle(指包含 UnityEngine.ObjectA 的 AssetBundle)。

更进一步,如果有多个对象(UnityEngine.ObjectA1、UnityEngine.ObjectA2、UnityEngine.ObjectA3......)引用了同一个被依赖对象(UnityEngine.ObjectB),那么被依赖对象将被拷贝多份,打包进各个对象各自的 AssetBundle。

如果一个 AssetBundle 存在依赖性,那么要注意的是,那些包含了被依赖对象的 AssetBundles,需要在你想要实例化的对象的加载之前加载。Unity 不会自动帮你加载这些依赖。

从 AssetBundles 中加载资源

现在,你已经成功下载了你的 AssetBundle,是时候从中加载一些资源。

通常的代码片段:

T objectFromBundle = bundleObject.LoadAsset<T>(assetName);

T 是你想加载的资源类型。

当你决定如何加载资源的时候,有一对方法供使用。我们可以使用 LoadAsset、LoadAllAssets 方法,以及与它们对应的异步方法: LoadAssetAsync、LoadAllAssetsAsync。

下面是一个从一个 AssetBundle 中同步加载资源的例子:

加载一个 GameObject:

GameObject gameObject = loadedAssetBundle.LoadAsset<GameObject>(assetName);

加载所有资源:

Unity.Object[] objectArray = loadedAssetBundle.LoadAllAssets();

现在,和上面展示的方法(要么返回你正在加载的对象,要么返回一组对象)不同的是,异步方法返回的是一个 AssetBundleRequest。

在可以使用资源前,你需要等待处理完成。如下:

AssetBundleRequest request = loadedAssetBundleObject.LoadAssetAsync<GameObject>(assetName);
yield return request;
var loadedAsset = request.asset;
以及:
AssetBundleRequest request = loadedAssetBundle.LoadAllAssetsAsync();
yield return request;
var loadedAssets = request.allAssets;
一旦你已经加载好你的资源,是时候行动了!你可以像使用 Unity 中的其他对象一样使用加载的对象。

加载 AssetBundle Manifests(资源清单)

加载 AssetBundle manifests 非常的有用。尤其是当处理 AssetBundle 依赖关系的时候。为了获取可以使用的 AssetBundleManifest,你需要加载一个额外的 AssetBundle(即那个和文件夹名称相同的文件),并且从中加载出一个 AssetBundleManifest 类型的对象。从 AssetBundle 中加载 manifest 完全和从中加载其他资源一样,如下:

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

现在,你可以通过上面例子获取到的 manifest 对象来使用 AssetBundleManifest 类的 API。从现在开始,你可以使用这个 manifest 来获取关于 AssetBundle 的信息,包括:依赖数据、hash 数据,以及版本变量数据。

还记得前面章节我们讨论过的,如果一个 bundleA 对 bundleB 有依赖,那么在从 bundleA 中加载任何资源之前,我们需要先加载 bundleB 吗?Manifest 对象就使得动态查找正在加载的依赖关系成为可能。比如我们想要加载一个名叫“assetBundle”的 AssetBundle 的所有依赖:

AssetBundle assetBundle = AssetBundle.LoadFromFile(manifestFilePath);
AssetBundleManifest manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] dependencies = manifest.GetAllDependencies(“assetBundle");
foreach(string dependency in dependencies)
{
    AssetBundle.LoadFromFile(Path.Combine(assetBundlePath, dependency));
}

现在,你已经加载了 AssetBundle、AssetBundle 依赖,以及其他资源,是时候讨论如何管理这些加载好的 AssetBundles 了。

在 Objects 被从场景中移除的时候,Unity 不会自动将它们卸载。资源的清理是在某个特定时机被触发,当然也可以手动触发。

知道什么时候加载和卸载一个 AssetBundle 很重要。不合时宜的卸载 AssetBundle 可能导致重复对象(duplicating objects)错误,或者其他未预料到的情况,比如纹理丢失

理解如何管理 AssetBundle 最重要的事是什么时候调用 AssetBundle.Unload(bool) 方法,以及该方法的参数应该传入 true 还是 false。该方法卸载 AssetBundle 的头信息;方法参数决定了是否同时卸载从 AssetBundle 中加载并实例化的所有 Objects。

如果你传入 true 参数,那么你从 AssetBundle 中加载的所有对象将被卸载,即便这些对象正在被使用。这就是我们前面提到的,导致纹理丢失的原因。

假设 Material M 是从 AssetBundle AB 中加载的,如下:

如果 AB.Unload(true) 被调用,那么任何使用 Material M 的实例都将被卸载并消除,即便它们正在场景中被使用。

如果 AB.Unload(false) 被调用,那么将切断所有使用 Material M 的实例与 AssetBundle AB 的联系。

如果 AssetBundle AB 在被卸载后不久再次被加载,Unity 并不会将已经存在的使用 Material M 的实例与 AssetBundle AB 重新联系。因此将存在两份被加载的 Material M。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值