热更新之Assetbundle——创建

最近实验下assetbundle的热更,本来以为很简单,就创建,上传,下载,加载。但实际上开发的时候才发现个中细节多且复杂。

创建本来以为就一句api就可以了,但是实际操作起来,才发现想的过于简单。

首先,命名,那么多图集,预设,不可能去手动命名,所以要写一个工具。工具原理就是根据文件名,去自动修改文件的assetbundleName以及后缀assetBundleVariant。需要注意的是,这两个参数并不记录在文件本身,而是存在文件的.meta文件里面,文本编辑器打开即可看到。我这边的实现是在project视图选择一个文件,然后去遍历这个文件所在文件夹的文件,根据名字,去给每个文件赋值(我这里所有一个图集都在一个文件夹,并且一个图集的资源都是同名,所以按照这个规则来赋值,规则根据项目实际情况来制定),代码如下:

public static Object[] Objs = new Object[] { };

    [MenuItem("Assetbundle/AutoSetAltasBundleNames")]
    static void SetAltasBundleNames()
    {
        Objs = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
        string path = AssetDatabase.GetAssetPath(Objs[0]);

        string parentPath = Path.GetDirectoryName(path);

        string[] files = Directory.GetFiles(parentPath);

        for (int i = 0; i < files.Length; i++)
        {
            if (Path.GetExtension(files[i]) == ".meta") continue;
            string name = Path.GetFileNameWithoutExtension(files[i]);

            if (name.EndsWith(".mat") || name.EndsWith("_a") || name.EndsWith("Avatar"))
                name = name.Replace(".mat", "").Replace("_a", "").Replace("Avatar", "");

            AssetImporter asset = AssetImporter.GetAtPath(files[i]);
            asset.assetBundleName = assetBundleLoadManager.assetType.altas.ToString() + "/" + name;
            asset.assetBundleVariant = "bundle";
        }
    }

首先将选中的对象放入objs数组,我这里只选择了一个,然后获取选择的对象路径,获取对象所在文件夹,获取该文件夹下所有对象的路径,遍历,获取筛选后每个对象的AssetImporter,按照规则赋值。只需看关键代码,其他代码因项目因人而异。

命名之后生成bundle,这里选择lz4压缩方式:

    [MenuItem("Assetbundle/CreateAssetbundle/LZ4_Compress")]
    static void CreateType2()
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }

        BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.Android);
    }

至此,bundle就全部生成到对应文件夹了,但是考虑到后面版本更新时,要去校验那些文件发生了改变,哪些文件需要更新,要更新的文件大小,所以还需要生成一个配置文件,记录所有bundle的大小,名字,后缀,md5值。其中path为ab包生成的目录。

public class assetBundleMsgInfo  {

    public string bundleName { get; set; }

    public long size { get; set; }

    public string hash { get; set; }

    public string crc { get; set; }

    public string BundleVariant { get; set; }
}


//创建文本文件,储存所有bundle信息,用于与服务端文件做对比,然后进行差异更新
    [MenuItem("Assetbundle/CreateBundlesMsgFile")]
    static void CreateBundlesMsgFile()
    {
        AssetBundle.UnloadAllAssetBundles(true);
        AssetBundle.UnloadAllAssetBundles(false);

        List<assetBundleMsgInfo> bundleMsgInfoList = new List<assetBundleMsgInfo>();

        AssetBundle asset = AssetBundle.LoadFromFile(Path.Combine(path, "AssetbundleFile"));
        AssetBundleManifest maniFest = asset.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        string[] assetArr = maniFest.GetAllAssetBundles();
        for (int i = 0; i < assetArr.Length; i++)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();

            FileStream fs = new FileStream(Path.Combine(path, assetArr[i]), FileMode.Open);
            md5.ComputeHash(fs);
            long length = fs.Length;


            fs.Close();

            byte[] hash = md5.Hash;

            StringBuilder str = new StringBuilder();

            foreach (byte item in hash)
            {
                str.Append(string.Format("{0:X2}", item));
            }

            Debug.Log(assetArr[i] + "---" + length + "---" + str);
            
            assetBundleMsgInfo info = new assetBundleMsgInfo();
            info.bundleName = assetArr[i];
            info.hash = str.ToString();
            info.size = length;
            info.BundleVariant = "bundle";
            bundleMsgInfoList.Add(info);
        }


        //写入文件

        if (File.Exists(Path.Combine(path, "bundleMsg")))
            File.Delete(Path.Combine(path, "bundleMsg"));

        File.Create(filePath).Close();//创建文件后,关闭文件流,否则写入流无法使用,有异常
        //Directory.CreateDirectory(filePath);//文件夹不存在时,需要先创建文件夹
        JsonData data = JsonMapper.ToJson(bundleMsgInfoList);
        createFile(Path.Combine(path, "bundleMsg"), data.ToString());

        AssetDatabase.Refresh();
    }


    static void createFile(string path, string sb)
    {
        //不要以utf-8写入,不然json从服务端解析数据时会有异常
        using (StreamWriter textWriter = new StreamWriter(path, false))
        {
            try
            {
                textWriter.Write(sb);
                textWriter.Flush();
                textWriter.Close();
                Debug.Log("complete!!!!!!");
            }
            catch (System.Exception e)
            {
                textWriter.Close();
                Debug.LogError(e.Message);
            }
        }
    }

先根据bundle的主manifest文件去获取所有的bundle,然后去遍历这些bundle文件,生成对应的md5值,存起来写入一个文件里面,其中md5的生成是网上搜到的,忘记出处了...其他代码感觉也没什么好解释的,属于一看就懂那种,应该吧...

最后只需创建个版本号文件,创建的步骤就属于完成了,文件内容只需要一个版本号而已。

代码解释没有特别仔细,主要是调用一些现成的api,没有比较复杂的逻辑在里面,所以就没有一句句去解释。json用的litjson。

补充!!!使用的是unity2017.2.1版本,assetbundle的打包会自动实现增量打包,不会全量打包。当时纠结这个纠结了好久。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值