Unity资源打包

什么是AssetBundle


  • AssetBundle是一个压缩包包含模型、贴图、预制体、声音、场景等资源,在游戏运行过程中被加载
  • 这个压缩包可以认为是一个文件夹,里面包含了多个文件。这些文件可以分为两类:serialized file 和 resource files(序列化文件和源文件)serialized file:资源被打碎放在一个对象中,最后统一被写进一个单独的文件(只有一个);resource files:某些二进制资源(图片、声音)被单独保存,方便快速加载

AssetBundle的主要作用


  • 游戏运行过程中可以被加载
  • AssetBundle自身保存着互相的依赖关系
  • 压缩包可以使用LZMA和LZ4压缩算法,减少包大小,更快的进行网络传输
  • 把一些可以下载内容放在AssetBundle里面,可以减少安装包的大小

AssetBundle打包


如下图所示,我们针对资源在Asset Labels中设置Asset Bundle名字

file

下面我们开始构建AssetBundle包

  • 创建一个文件夹命名Editor,创建一个编辑器扩展类CreateAssetbundles
using UnityEditor;
using System.IO;

public class CreateAssetbundles  {

    [MenuItem("AssetsBundle/Build AssetBundles")]
     static void BuildAllAssetBundles()//进行打包
    {
        string dir = "AssetBundles";
        // 判断该目录是否存在
        if (Directory.Exists(dir) == false)
        {
            // 在工程下创建AssetBundles目录
            Directory.CreateDirectory(dir);
        }
        // 参数一为打包到哪个路径,参数二压缩选项  参数三 平台的目标
        BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None,BuildTarget.StandaloneWindows64);
    }
}
BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长。使用之前需要整体解压。一旦被解压,这个包会使用LZ4重新压缩。使用资源的时候不需要整体解压。在下载的时候可以使用LZMA算法,一旦它被下载了之后,它会使用LZ4算法保存到本地上。
BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,包大,加载快
BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。
注意使用LZ4压缩,可以获得可以跟不压缩想媲美的加载速度,而且比不压缩文件要小。

所以一般我们选择LZ4的打包压缩方式

AssetBundle加载


  • 从内存加载使用LoadFromMemoryAsync
  • 从本地文件加载可以使用LoadFromFile
  • 从服务器上Web上加载可以使用UnityWbRequest

我们根据上面所给的三种方式,分别进行说明

LoadFromMemoryAsync方式

using UnityEngine;
using System.IO;
using System.Collections;
public class LoadFromFileExample : MonoBehaviour {

    IEnumerator Start () {
        string path = "AssetBundles/iOS/common_icons";
        // 第一种加载AB的方式 LoadFromMemoryAsync
        // 异步加载
        AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(path));
        yield return request;
        AssetBundle ab = request.assetBundle;
        // 同步方式
        // AssetBundle ab =  AssetBundle.LoadFromMemory(File.ReadAllBytes(path));

         // 使用里面的资源
        Object[] obj = ab.LoadAllAssets<GameObject>();//加载出来放入数组中
        // 创建出来
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
    }
}

LoadFromFile方式

using UnityEngine;
using System.Collections;

public class LoadFromFileExample : MonoBehaviour {

    IEnumerator Start () {
        string path = "AssetBundles/iOS/common_icons";
        // 第二种加载方式 LoadFromFile
        // 异步加载
        AssetBundleCreateRequest request = AssetBundle.LoadFromFileAsync(path);
        yield return request;
        AssetBundle ab = request.assetBundle;
        // 同步加载
        // AssetBundle ab = AssetBundle.LoadFromFile(path);

        // 使用里面的资源, 加载出来放入数组中
        Object[] obj = ab.LoadAllAssets<GameObject>();
        // 创建出来
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
     }
}

UnityWbRequest方式

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class LoadFromFileExample : MonoBehaviour {

    IEnumerator Start () {
        // 第三种加载方式使用UnityWbRequest服务器加载使用http本地加载或远程加载使用file
        string uri = @"http://127.0.0.1:8080/AssetBundles/iOS/common_icons";
        UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri);
        yield return request.Send();
        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
        // 使用里面的资源, 加载出来放入数组中
        Object[] obj = ab.LoadAllAssets<GameObject>();
        // 创建出来
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
    }
}

AssetBundle分组策略


  • 把经常更新的资源放在一个单独的包里面,跟不经常更新的包分离
  • 把需要同时加载的资源放在一个包里面
  • 可以把其他包共享的资源放在一个单独的包里面
  • 把一些需要同时加载的小资源打包成一个包
  • 如果对于一个同一个资源有两个版本,可以考虑通过后缀来区分

AssetBundle中的依赖


什么叫做依赖呢?比如我们两个预设(Prefab)需要用到同样的纹理(Texture),那么Prefab和Texture之间就存在着依赖关系,如果我们对两个预设分别打包,Texture就会存在两份,包体就会变大,我们该如何解决这个问题呢?

  • 首先将用到的同样的纹理图打包成AssetBundle
  • 然后分别打包两个预设

这样就可以缩减打包出来的体积大小
此时我们再加载AssetBundle中的Prefab,同时需要将他们依赖的纹理也加载到内存中,否则会出现纹理丢失的情况。如下所示

using UnityEngine;
public class LoadFromFileExample : MonoBehaviour {
    void Start () {
        AssetBundle ab = AssetBundle.LoadFromFile("AssetBundles/iOS/Prefab1");
        AssetBundle textureAB = AssetBundle.LoadFromFile("AssetBundles/iOS/texture");
        // GameObject go = ab.LoadAsset<GameObject>("Prefab1");
        // Instantiate(go);
        Object[] obj = ab.LoadAllAssets<GameObject>();
        // 创建出来
        foreach (Object o in obj)
        {
            Instantiate(o);
        }
    }
}

在打包完AssetBundle之后会出现AssetBundlesAssetBundles.manifest两个文件,所有打包出来的AssetBundle都会放在其中;所以我们可以读取这两个文件,从而达到获取所有AssetBundle的目的。

AssetBundle manifesAB = AssetBundle.LoadFromFile("AssetBundles/iOS/AssetBundles");
AssetBundleManifest manifest= manifesAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
foreach (string name in manifest.GetAllAssetBundles())
{
    print(name);
}

然后我们利用manifest文件加载某个AssetBundle的依赖

...
AssetBundle manifesAB = AssetBundle.LoadFromFile("AssetBundles/AssetBundles");
AssetBundleManifest manifest= manifesAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
foreach (string name in manifest.GetAllAssetBundles())
{
    print(name);
}
string []strs = manifest.GetAllDependencies("Prefab1");
foreach (var name in strs)
{
    AssetBundle.LoadFromFile("AssetBundles/" + name);
}
...

AssetBundle的卸载

一般我们使用AssetBundle.Unload对资源进行卸载工作

  • AssetBundle.Unload(true) 卸载所有资源,即使有资源被使用着
  • AssetBundle.Unload(false)卸载所有没用被使用的资源
  • Resources.UnloadUnusedAssets

文件校验

文件校验可以在文件传输的时候保证文件的完整性,例如A在给我传输了一个文件之前会生成一个校验码,对于这个文件只会生成这一个唯一的校验码,只要传输给我的文件有一点不一样那么校验码就会完全不同。所以A在传输给我文件的时候会把文件和校验码都传输给我,当我取到这个文件的时候我也会使用和A同样一个算法去生成这个文件的校验码,然后拿这个值和A传输给我的校验码比对,如果一样说明这个文件是完整的,如果不一样那么就重新传输。

CRC MD5 SHA1几种方式对比

  • 算法不同。CRC采用多项式除法,MD5和SHA1使用的是替换、轮转等方法
  • 校验值的长度不同。CRC校验位的长度跟其多项式有关系,一般为16位或32位;MD5是16个字节(128位);SHA1是20个字节(160位)
  • 校验值的称呼不同。CRC一般叫做CRC值;MD5和SHA1一般叫做哈希值(Hash)或散列值
  • 安全性不同
  • 效率不同,CRC的计算效率很高;MD5和SHA1比较慢
  • 用途不同。CRC一般用作通信数据的校验;MD5和SHA1用于安全(Security)领域

Unity Asset Bundle Browser Tool

下载地址:
https://github.com/Unity-Technologies/AssetBundles-Browser

参考资料

https://www.jianshu.com/p/5d4145cd900c

欢迎留言

avatar
  Subscribe  
Notify of