zoukankan      html  css  js  c++  java
  • unity Assetbundle 使用

    本文的主要内容是分析5.X版本的AssetBundle机制(包括创建资源包、压缩资源包、加载资源包和从资源包中加载/卸载资源等几个方面)及其关键的API使用方式。
    AssetBundle是Unity推荐的资源管理方式,官方列举了诸如热更新,压缩,灵活等等优点。

    使用步骤
    一、打包
    1.通过Editor中的UI为AssetBundle标记资源。而且一个资源和对应的AssetBundle的映射将会在资源数据库(AssetDatabase)中被创建。


    2.BuildPipeline.BuildAssetBundles():我们只需要提供一个输出AssetBundle的地址即可。引擎将自动根据资源的assetbundleName属性(即在上文中UI中设置的值)批量打包,自动建立Bundle以及资源之间的依赖关系。
    Unity3D为我们提供了唯一的API用来打AssetBundle包。即:BuildPipeline.BuildAssetBundles
    在脚本中调用BuildPipeline.BuildAssetBundles,U3D将自动根据资源的assetbundleName属性批量打包,自动建立Bundle和资源之间的依赖关系。在资源的Inpector界面最下方可设置该资源的assetbundleName,每个assetbundleName对应一个Bundle,即assetbundleName相同的资源会打在一个Bundle中。如果所依赖的资源设置了不同的assetbundleName,则会自动与之建立依赖关系,避免出现冗余,从而减小Bundle包的大小。当然,除了可以指定assetbundleName,我们还可以在Inpector中设置另一个名字,即variant。在打包时,variant会作为后缀添加在assetbundleName之后。相同assetbundleName,不同variant的Bundle是可以相互替换的。

    设置好之后,我们只需要创建一个新的脚本,通过编辑器拓展调用BuildPipeline.BuildAssetBundles方法即可:

    BuildPipeline.BuildAssetBundles方法的参数
    outputPath:输出目录,一般我们设置为  Application.streamingAssetsPath + Bundle的目标路径和Bundle名称
    targetPlatform:目标平台,在安卓,IOS,PC下,我们需要传入不同的平台标识,以打出不同平台适用的包,注意,Windows平台下打出来的包,不能用于IOS
    BuildAssetBundleOptions:BuildAssetBundleOptions.CollectDependencies会去查找依赖,BuildAssetBundleOptions.CompleteAssets会强制包含整个资源,BuildAssetBundleOptions.DeterministicAssetBundle会确保生成唯一ID,在打包依赖时会有用到

    Unity3D引擎为我们提供了三种压缩策略来处理AssetBundle的压缩,即:LZMA格式、LZ4格式、不压缩。
    LZMA格式:在默认情况下,打包生成的AssetBundle都会被压缩。在U3D中,AssetBundle的标准压缩格式便是LZMA(LZMA是一种序列化流文件),因此在默认情况下,打出的AssetBundle包处于LZMA格式的压缩状态,在使用AssetBundle前需要先解压缩。
    使用LZMA格式压缩的AssetBundle的包体积最小(高压缩比),但是相应的会增加解压缩时的时间。
    LZ4格式: Unity 5.3之后的版本增加了LZ4格式压缩,由于LZ4的压缩比一般,因此经过压缩后的AssetBundle包体的体积较大(该算法基于chunk)。但是,使用LZ4格式的好处在于解压缩的时间相对要短。若要使用LZ4格式压缩,只需要在打包的时候开启BuildAssetBundleOptions.ChunkBasedCompression即可。
    BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
    BuildAssetBundleOptions.ChunkBasedCompression);
    不压缩:我们也可以不对AssetBundle进行压缩。没有经过压缩的包体积最大,但是访问速度最快。若要使用不压缩的策略,只需要在打包的时候开启BuildAssetBundleOptions.UncompressedAssetBundle即可。
    BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
    BuildAssetBundleOptions.UncompressedAssetBundle);

    在打包的时候,我们需要对包的大小和数量进行一个平衡,所有资源打成一个包,一个资源打一个包,都是比较极端的做法,他们的问题也很明显,更多情况下我们需要灵活地将他们组合起来
    打成一个包的缺点是加载了这个包,我们不需要的东西也会被加载进来,占用额外内存,而且不利于热更新 打成多个包的缺点是,容易造成冗余,首先影响包的读取速度,然后包之间的内容可能会有重复,且太多的包不利于资源管理哪些模块打成一个包,哪些模块打成多个包,需要根据实际情况来,例如游戏中每个怪物都需要打成一个包,因为每个怪物之间是独立的,例如游戏的基础UI,可以打成一个包,因为他们在各个界面都会出现
     PS.想打包进AssetBundle中的二进制文件,文件名的后缀必须为“.bytes”

    二、加载
    首先获取AssetBundle对象,第二从AssetBundle中加载目标资源。在运行时加载AssetBundle对象主要可以分为两大类途径:
    1.先获取WWW对象,再通过WWW.assetBundle加载AssetBundle对象:
    public WWW(string url),直接调用WWW类的构造函数,目标AssetBundle所在的路径作为其参数,构造WWW对象的过程中会加载Bundle文件并返回一个WWW对象,完成后会在内存中创建较大的WebStream(解压后的内容,通常为原Bundle文件的4~5倍大小,纹理资源比例可能更大),因此后续的AssetBundle.LoadAsset可以直接在内存中进行。
    public static WWW LoadFromCacheOrDownload(string url, int version, uint crc = 0),WWW类的一个静态方法,调用该方法同样会加载Bundle文件同时返回一个WWW对象,和上一个直接调用WWW的构造函数的区别在于该方法会将解压形式的Bundle内容存入磁盘中作为缓存(如果该Bundle已在缓存中,则省去这一步),完成后只会在内存中创建较小的SerializedFile,而后续的AssetBundle.LoadAsset需要通过IO从磁盘中的缓存获取。LoadFromCacheOrDownload会记录所有Bundle的使用情况,并在适当的时候删除最近很少使用的资源包,它允许存在两个版本号不同但名字一样的资源包,这意味着你更新这个资源包之后,如果没有更新代码中的版本号,你可能取到的会是旧版本的资源包,从而产生其他的一些BUG。另外,当你的磁盘空间不足的时候(硬盘爆了),LoadFromCacheOrDownload只是一个普通的new WWW
    2.直接加载AssetBundle对象:
    public static AssetBundle LoadFromFile(string path, uint crc = 0):新的从文件创建加载AssetBundle方法,loadFromFile方法支持上一节中提到的几个压缩格式,针对LZ压缩格式和未压缩的磁盘上的bundle文件,该方法会直接加载。针对使用默认的LZMA压缩格式压缩的bundle文件,该方法会在幕后先将bundle文件解压后再加载。这是最快的加载AssetBundle的方式。该方法是同步版本,还有异步版本:LoadFromFileAsync。
    public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0):从内存中获取Bundle的二进制数据,同步地创建AssetBundle对象。该方法一般用在经过加密的数据上,经过加密的流数据经过解密之后我们可以调用该方法动态的创建AssetBundle对象。该方法是同步版本,还有异步版本:LoadFromMemoryAsync。
    三、资源加载
    LoadAsset:从资源包中加载指定的资源
    LoadAllAsset:加载当前资源包中所有的资源.
    LoadAssetAsync:从资源包中异步加载资源
    在Bundle中加载的Prefab是不能直接使用的,它需要被实例化之后,才能使用,而对于这种Prefab,实例化之后,这个Bundle就可以被释放了
    GameObject obj = GameObject.Instantiate(bundle.Load("MyPrefab")) as GameObject;
    bundle.Load("MyPrefab", typeof(GameObject))加载的时候最好传入资源的类型

    四、针对项目的建议
    由于以上分析的几种加载手段各有各的使用情景和特点。因此建议在我们的项目中按照以下情景使用这些方法:
    1.随游戏一同发布的AssetBundle(一般位于StreamingAssets文件夹中):在打AssetBundle包时,使用LZ4压缩格式进行打包(开启BuildAssetBundleOptions.ChunkBasedCompression即可)。
    2.在运行时需要加载AssetBundle对象时,使用LoadFromFile方法进行加载。
    这样做的好处是:即可以将AssetBundle文件压缩,又可以兼顾加载速度,且节约内存。
    3.在打AssetBundle包时,使用默认的LZMA格式压缩。
    4.使用WWW.LoadFromCacheOrDownload方法下载并缓存AssetBundle包文件。

    一直想把之前工作、学习时记录的文档整理到博客上,一方面温故而知新,一方面和大家一起学习 -程序小白
  • 相关阅读:
    css !import
    算法
    java web 运动前端
    oauth 2
    js 优化
    js 代码优化 (写的可以)
    2015/08/17 《有两条均线,你应该注意》
    佳能相机操作 EDSDK 教程 C# 版本
    2015/8/14——了2000股,是否正确呢——明天待验证?
    系统架构师考试——程序计数器 PC, 指令寄存器IR、状态寄存器SR、通用寄存器GR
  • 原文地址:https://www.cnblogs.com/wang-jin-fu/p/8144456.html
Copyright © 2011-2022 走看看