什么是AssetBundle?(unity官方文档翻译)

AssetBundle是unity提供的一个特定平台的归档文件(archive file),可以在运行时加载。AssetBundle包可以明确的表示互相之间的依赖关系。例如a包中的材质引用了b包中的贴图。为了在网络上高效的传输。AssetBundle可以更具实际需求选择内置的压缩算法。
AssetBundle对下载DLC很有用,可以减少安装包大小,优化终端平台的资源加载,减少运行时的内存压力。
上面是unity官方文档的翻译,AssetBundle功能总结有:游戏资源更新,减少游戏安装包大小,优化资源加载

如何使用AssetBundle

一、给对象设置AssetBundle属性
首先AssetBundle可以对所有的资源进行打包(预制体,音频,贴图,材质,甚至场景),当你选择对象的时候,如果Inspector上有AssetBundle属性的设置,就说明他可以打包。
Unity学习之_AssetBundle

第一个None是 包名,也可以是 目录/包名(可以创建目录),第二个None是后缀。这两个属性都是可以自定义的。(这里这个材质的包名是material 后缀是u3d,注意都是强制小写)

二、创建打包工具
当我们把要打包的材质定义好AssetBundle属性之后,就可以开始打包操作了。所有我们这里要先写一个在编辑器模式下运行的打包工具。

using System.IO;
using UnityEditor;

public class CreatAB
{
    //在Unity菜单栏Assets列表下面创建一个快捷方法按钮
    [MenuItem("Assets/CreatAssetBundles")]
    static void CreatAssetBundles()
    {
        //路径(这是相对路径,项目的跟目录)
        string path = "AssetBundless";
        //判断路径是否存在
        if(!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
        //打包
        BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
    }
}

介绍这里用到的几个方法
Directory.Exists(路径):类方法 判断给定的路径是否是已经存在的目录 是返回true 反之false
Directory.CreateDirectory(路径):类方法 在指定路径下创建一个目录
BuildPipeline.BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform):类方法 在编辑器模式下打包所有指定的AssetBundle对象

  • outputPath:输出目录(只能输出到现有目录中)
  • assetBundleOptions:包的构建方式(使用那种压缩算法)
  • targetPlatform:目标平台(AssetBundle包不是跨平台的,只能在指定平台使用)
  • 返回值: AssetBundleManifest类型文件 包含了所有AssetBundle包的列表和依赖关系

写好方法后开始打包,这里我先创建一个Cube,然后将上面那个指定了AssetBundle属性的材质给到Cube,再把这个Cube做成预制体,并给这个Cube设置一下AssetBundle属性(包名是cube,后缀是u3d)
Unity学习之_AssetBundle
三、打包
我们直接选择Assets找到CreatAssetBundles点击,等待一下就可以了,然后我们看一下打包文件夹里面有些文件。直接打开项目的根目录有一个AssetBundles文件夹,打开他可以看到下面的6个文件。先从后缀上看,一种是我们设置的u3d的后缀结尾的文件,一种是Manifest后缀结尾的文件。

  • .u3d 结尾的文件是Assetbundle包本体
  • .Manifest 结尾的文件是给人看的,让我们查看包的属性,这个文件可以直接用记事本打开,可以查询效验码、包里包含的资源对象,包的依赖关系,
  • AssetBundle.Manifest 中包含的是所有包的信息 给人看的
  • AssetBundle 这个种也包含的是所有包的信息 只不过这个文件是计算机看的 就是打包方法BuildPipeline.BuildAssetBundles的返回值
    Unity学习之_AssetBundle
    四、使用AssetBundle包
    使用AssetBundle包的API有好几种,这里介绍的是既可以从本地加载也可以从服务器加载的一种方法
    UnityWebRequest 异步方法(更多方法查看Unity官方手册
    先创建一个脚本,然后把脚本挂在到一个空物体上,编辑脚本
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class LoadAssetBundleFile : MonoBehaviour
{        
    private void Start()
    {
        StartCoroutine("UWR");
    }

    //异步加载方法需要使用协程
    IEnumerator UWR()
    {
        //路径 可以本地也可以服务器 本地需要加前缀file:///
        string [email protected]"file///F:\Unity Test\CSDN__Blog\AssetBundles\cube.u3d";
        //创建下载资源请求
        UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(path);
        //开始异步下载资源并等待完成
        yield return request.SendWebRequest();

        //取得下载好的资源中的AB包(第一种) DownloadHandlerAssetBundled.GetContent方法
        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
        //取得下载好的资源种的AB包(第二种) 格式转换
        //AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;

        //使用AB包            LoadAsset<对象类型>(对象名)       
        GameObject cube = ab.LoadAsset<GameObject>("Cube");
        Instantiate(cube);
    }
}

Unity学习之_AssetBundle
运行后会发现Cube被实例化出来但是缺少材质,这是因为我们没有加载材质的AssetBundle包,这就关系到AssetBundle打包时的依赖关系:上面这个例子中我们分别把cube的预制体和他所使用的材质进行的打包,所以在我们单独使用cube预制体的ab包时就是没有材质的,但是如果我们将材质的AssetBundle属性设为None,再进行打包。之后我们在次运行同样的代码,实例化出来的cube就会带有材质。
这就说明当你给自身使用的材质设置了AssetBundle属性并打包后,cueb的ab包就不会包含他自身使用材质的数据,这时cube的ab包和材质的ab包就建立了依赖关系。如果没有打包你使用的材质的,那么cube包就会自带材质的数据,这一点对比下面这个没有单独打包材质的cube大小和上图cube的大小就知道了(适用于所有可以打包的对象)。

(依赖打包只需要将依赖的资源打包,就可以建立依赖关系(这是unity控制的),这种做法可以避免出现重复资源的打包)
Unity学习之_AssetBundle
那么如何再脚本里获取不同包之间的依赖关系呢?这就要用到 AssetBundles文件 我们先把材质的AssetBundls的属性设置回来然后重新打包。之后运行发现cube还是没有材质的,让后我们加上这段代码。再次运行就已经有材质了。

      //取得AB包的依赖关系
        //首先拿到AssetBundles文件 (这是最简单的加载AB包方式,返回值就是加载的ab包 属于同步加载)
        AssetBundle manifestAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
        //拿到AssetBundles文件中的manifest文件
        AssetBundleManifest manifest = manifestAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");

        //取得对应AB包的依赖关系
        //GetAllDependencies(AB包名) 返回值是这个AB包所依赖的所有AB包包名
        string[] strs = manifest.GetAllDependencies("cube.u3d");
        foreach (string name in strs)
        {
            //加载cubeAB包所依赖的所有资源,这里就只有一个材质资源
            AssetBundle.LoadFromFile("AssetBundles/" + name);
        }

这里的加载或者上面说的下载都是一个意思,是指将AB包中的数据存到内存中,但什么时候使用要看代码的调度,既有手动比如实例化cube,也有自动比如cube自动找到内存上的材质并使用。
(注意:如果一个资源有依赖资源,在使用这个资源前要最好先加载他的依赖资源,实测是不用的,这里我们就是后加载的,但是逻辑上最好还是遵守避免出现不必要的错误)

AssetBundle打包策略

  • 把经常更新的资源放在一个单独的包,不经常跟新的放一个包
  • 需要同时加载的资源放一个包
  • 共享的资源单独放一个包
  • 一个场景可以内用的资源可以放一个包
  • 等等 这些策略都是更具项目需要灵活调整的

分享让知识变得有意义!后续会继续更新一些学习中问题。
OJMars
InTheMars

相关文章: