Unity热更_打AssetBundles包

Unity开发离不了热更新,现在市面上有很多的热更方案,XLua、ToLua以及C#热更方案ILRuntime,以腾讯的XLua为例,若要实现热更新,AssetBundles是不可规避的一个环节,这其中包括AssetBundles的生成与加载,本文以生成AssetBundles为主,主要来讲自动化打AssetBundles包,至于AssetBundles包体的加载抽时间会再写一篇博客。

手动添加AssetBundle标签方式

这是最常见的AssetBundle打包方式,给需要打Bundle包的预制体增加AssetBundle标签和后缀,然后在代码中实现Bundle的生成,这种方式在这里不做介绍,因为在百度上很容易就能搜到很多内容。

全自动打AssetBundle包方式

这种方式只要你知道需要打Bundle包的文件夹路径就可以打Bundle包无论是预制体、Lua脚本、或者字体、贴图等等都可以自动生成Bundle包体,方便快捷,省去手动添加标签的繁琐。

我把所有的预制体都放在了BundleResources文件夹下
所有的Lua脚本放在了Lua文件夹下,
通过代码把预支体和Lua都打成AssetBundle包
生成Md5文件,后期热更时需要对比Md5进行资源更新
生成map文件,记录资源和AssetBundle包的对应关系
直接上代码,注释很清晰

using System.Collections;using System.Collections.Generic;using System.IO;using UnityEditor;using UnityEngine;public class AssetsBundleEditor : Editor{    public static string luaDirName = "Lua";//Lua原文件文件夹    public static string tempLuaDirName = "TempLua";//Lua文件使用文件夹    public static string assetsDirName = "AssetBundles";//AssetBundle文件夹名    public static string prefabsDirName = "BundleResources";//所有预制体的文件夹名    public static string extName=".unity3d";//AssetBundle文件后缀名    public static List abList = new List();    [MenuItem("SJL/BuildAndroid")]    static void BuildAndroid() {//出Android包体,可根据需求配置其他的打包方式        Build(BuildTarget.Android);    }    static string GetStreamingAssets() {        return Application.streamingAssetsPath;    }    //打Bundle包    static void Build(BuildTarget buildTarget) {        string assetsBundlePath = GetStreamingAssets() + "/" + assetsDirName;        if (Directory.Exists(assetsBundlePath))        {            Directory.Delete(assetsBundlePath, true);        }        Directory.CreateDirectory(assetsBundlePath);        AssetDatabase.Refresh();        abList.Clear();        LuaCopyToTempLua();        InitLuaABList();        InitPrefabsABList();        BuildAssetBundleOptions options = BuildAssetBundleOptions.DeterministicAssetBundle | BuildAssetBundleOptions.ChunkBasedCompression;        BuildPipeline.BuildAssetBundles(assetsBundlePath, abList.ToArray(), BuildAssetBundleOptions.None, buildTarget);        CreateMd5File();        CreateMapFile();        AssetDatabase.Refresh();        Debug.Log("打AB包成功:\n"+System.DateTime.Now.ToString("yyyy-MM-dd||hh:mm:ss"));    }    //Lua文件夹下的lua文件转移至TempLua文件夹下    static void LuaCopyToTempLua() {        string luaDir = Application.dataPath + "/" + luaDirName;        string tempDir = Application.dataPath + "/" + tempLuaDirName;        if (!Directory.Exists(luaDir))        {            return;        }                string[] files = Directory.GetFiles(luaDir, "*.lua", SearchOption.AllDirectories);        if (files == null||files.Length==0)        {            return;        }        if (Directory.Exists(tempDir))        {            Directory.Delete(tempDir,true);        }        for (int i = 0; i < files.Length; i++)        {            string filePath = files[i];            string dirPath = Path.GetDirectoryName(filePath);            string tempDirPath = tempDir + dirPath.Replace(luaDir, string.Empty);            if (!Directory.Exists(tempDirPath))            {                Directory.CreateDirectory(tempDirPath);            }            string tempFilePath = tempDirPath + filePath.Replace(dirPath, string.Empty) + ".bytes";            File.Copy(filePath, tempFilePath, true);        }        AssetDatabase.Refresh();    }    //将Lua添加到AssetBundleBuild列表    static void InitLuaABList() {        string tempLuaDirPath = Application.dataPath + "/" + tempLuaDirName;        string[] dirArr = Directory.GetDirectories(tempLuaDirPath);        string bundleName = "lua/lua_" + tempLuaDirName.ToLower() + extName;        AddABList(bundleName,"Assets/"+tempLuaDirName,"*.bytes");        for (int i = 0; i < dirArr.Length; i++)        {            string dirPath = dirArr[i];            bundleName = "lua/lua_"+dirPath.Replace(tempLuaDirPath,"").Replace("/","").ToLower()+extName;            string path = "Assets"+dirPath.Replace(Application.dataPath, "");            AddABList(bundleName,path,"*.bytes");        }            }    //将预制体添加到AssetBundleBuild列表    static void InitPrefabsABList() {        string prefabsDirPath = Application.dataPath + "/" + prefabsDirName;        string[] dirArr = Directory.GetDirectories(prefabsDirPath);        string bundleName = "prefab/prefab_"+prefabsDirName.ToLower() + extName;        AddABList(bundleName,"Assets/"+prefabsDirName, "*.prefab");        for (int i = 0; i < dirArr.Length; i++)        {            string dirPath = dirArr[i];            bundleName = "prefab/prefab_"+dirPath.Replace(prefabsDirPath, "").Replace("/", "").ToLower() + extName;            string path = "Assets" + dirPath.Replace(Application.dataPath, "");            AddABList(bundleName, path, "*.prefab");        }    }    ///     /// 添加文件至AssetBundleBuild列表    ///     ///     /// 文件夹相对路径(例如:Assets/...)    /// 筛查条件    static void AddABList(string bundleName,string path,string pattern) {        string[] files = Directory.GetFiles(path,pattern);        if (files==null||files.Length==0)        {            return;        }        for (int i = 0; i < files.Length; i++)        {            files[i] = files[i].Replace("\\","/");        }        AssetBundleBuild abBuild = new AssetBundleBuild();        abBuild.assetBundleName = bundleName;        abBuild.assetNames = files;        abList.Add(abBuild);    }    //创建Md5文件    static void CreateMd5File() {        string assetBundlePath = GetStreamingAssets() + "/" + assetsDirName;        string mainBundle = assetBundlePath + "/AssetBundles";        string md5FilePath = assetBundlePath + "/" + "files_md5.md5";        if (File.Exists(md5FilePath))        {            File.Delete(md5FilePath);        }        List<string> mPaths = new List<string>();        List<string> mFiles = new List<string>();        string[] files = GetDirFiles(assetBundlePath,new string[] {".meta",".DS_Store"});        if (files==null||files.Length==0)        {            return;        }        foreach (var item in files)        {            mFiles.Add(item);        }        FileStream fs = new FileStream(md5FilePath,FileMode.Create);        StreamWriter sw = new StreamWriter(fs);        for (int i = 0; i < mFiles.Count; i++)        {            string file = mFiles[i];            if (string.IsNullOrEmpty(file)||file.EndsWith(".meta")||file.Contains(".DS_Store"))            {                continue;            }            string md5 = FileToMd5(file);            long size = GetFileSize(file);            string fileName = file.Replace(assetBundlePath+"/",string.Empty);            string str =fileName+"|"+ md5 + "|" + size;            sw.WriteLine(str);        }        sw.Close();        fs.Close();    }    //创建Map文件    static void CreateMapFile()    {        string assetBundlePath = GetStreamingAssets() + "/" + assetsDirName;        string mapFilePath = assetBundlePath + "/" + "files_map.map";        if (abList == null || abList.Count == 0)        {            return;        }        if (File.Exists(mapFilePath))        {            File.Delete(mapFilePath);        }        FileStream fs = new FileStream(mapFilePath, FileMode.Create);        StreamWriter sw = new StreamWriter(fs);        string[] filesArr = null;        string abName = null;        string fileName = null;        foreach (AssetBundleBuild ab in abList)        {            filesArr = ab.assetNames;            abName = ab.assetBundleName;            for (int i = 0; i < filesArr.Length; i++)            {                fileName = filesArr[i];                if (fileName.EndsWith(".meta") || fileName.EndsWith(".DS_Store"))                {                    continue;                }                fileName = fileName.Replace("Assets/", string.Empty);                sw.WriteLine(fileName + "|" + abName);            }        }        sw.Close();        fs.Close();    }    //文件转化为Md5    static string FileToMd5(string file)    {        try        {            FileStream fs = new FileStream(file, FileMode.Open);            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();            byte[] retVal = md5.ComputeHash(fs);            fs.Close();            System.Text.StringBuilder sb = new System.Text.StringBuilder();            for (int i = 0; i < retVal.Length; i++)            {                sb.Append(retVal[i].ToString("x2"));            }            return sb.ToString();        }        catch (System.Exception ex)        {            throw new System.Exception("md5file() fail, error:" + ex.Message);        }    }    //获取文件大小    static long GetFileSize(string filePath) {        long size = 0;        if (!File.Exists(filePath))        {            size = -1;        }        else        {            FileInfo info = new FileInfo(filePath);            size = info.Length;        }        return size;    }    ///     /// 得到文件夹下所有的文件    ///     /// 文件夹    /// 需要剔除的后缀名    ///     static string[] GetDirFiles(string dirPath,string[] useLessSuffixArr) {        List<string> fileList = new List<string>();        string[] files = Directory.GetFiles(dirPath,"*",SearchOption.AllDirectories);        if (files==null||files.Length==0)        {            return null;        }        for (int i = 0; i < files.Length; i++)        {            string file = files[i];            bool isTrue = true;            for (int j = 0; j < useLessSuffixArr.Length; j++)            {                string extension = useLessSuffixArr[j];                if (Path.GetExtension(file)==extension)                {                    isTrue = false;                    break;                }            }            if (isTrue)            {                fileList.Add(file);            }        }        return fileList.ToArray();    }}

unity menuitem_Unity热更_打AssetBundles包相关推荐

  1. unity python做热更_[专栏作家]基于ILRuntime的完整C#热更方案

    原标题:[专栏作家]基于ILRuntime的完整C#热更方案 好久不见.最近一段时间公司二次创业,实在是忙的脚打后脑勺,有段时间没来跟大家分享心得了,昨天终于有了一个初步的完结,也终于有时间和精力跟大 ...

  2. unity 代码热更+资源管理框架总结

    游戏要做热更涉及到什么方面呢 首先就是代码热更,然后就是资源热更 这些热更新都依赖于打AssetBundle 然而打AssetBundle 你还要上传服务器-对比更新-客户端下载-加载-卸载这些流程 ...

  3. 服务器协议热更_汽车和电话的开放协议,以及更多开放源新闻

    服务器协议热更 在本周的开源新闻摘要中,我们将探讨开源数据库的采用,Open edX课程的知识共享许可,Microsoft Windows的SSH等! 开源新闻:2015年5月30日至6月5日 为什么 ...

  4. Unity ToLua热更框架使用教程(1)

    从本篇开始将为大家讲解ToLua在unity当中的使用教程. Tolua的框架叫LuaFramework,首先附上下载链接: https://github.com/jarjin/LuaFramewor ...

  5. Unity 游戏用XLua的HotFix实现热更原理揭秘

    本文通过对XLua的HoxFix使用原理的研究揭示出来这样的一套方法.这个方法的第一步:通过对C#的类与函数设置Hotfix标签.来标识需要支持热更的类和函数.第二步:生成函数连接器来连接LUA脚本与 ...

  6. unity android so热更,惊鸿哥的港湾

    是的,没错,前两篇(<如何在Debian中编译Unity Mono生成Android版的libmono.so>.<如何在CentOS/RHEL中编译Unity Mono生成Andro ...

  7. Unity UI xlua 热更:还原塞尔达旷野之息 (持续更新:已补充箭头动效)

    整了个小Demo仿照<塞尔达传说:旷野之息>,实现 鼠标悬停在Button上时,能够改变Button-Text颜色,并且在Button前显示一个小箭头 标题鼠标指针悬停和移走,改变标题颜色 ...

  8. Java和U3D比较,Unity热更方案 ILRuntime 和 toLua的比较

    前言 目前市面上流行的热更方案就是lua系列和ILRuntime,选取哪一种需要根据自己的项目进行比对. 无论是ILRuntime还是toLua都是市面上有在用到的热更方案.直观上来讲,都可以通过把代 ...

  9. Unity Android DLL热更

    2019独角兽企业重金招聘Python工程师标准>>> 和 Unity Mono DLL加密 有异曲同工之处. 这里是为了能够在Android下热更C#代码 另外一个更高层次的是更新 ...

最新文章

  1. URAL 2027 URCAPL, Episode 1 (模拟)
  2. 01 小程序开发入门
  3. java分布式锁解决方案 redisson or ZooKeeper
  4. 关于《如何阅读一本书》
  5. 当Tomcat遇上Netty,我这一系列神操作,同事看了拍手叫绝
  6. 风控建模 python 知乎_风控建模基本要求及面试问题小结
  7. layui option 动态添加_layui中select的change事件、动态追加option
  8. Apache JMeter 压试 HTTP接口
  9. 骨干云池存储方式_你好,我存个对象(大误)漫谈对象存储
  10. C语言之10/16进制字符串和数字转换(四)
  11. django数据库设置为MySQL
  12. 管理感悟:你是产品的第一个用户
  13. JEB动态调试debug模式
  14. gerund - 动名词
  15. android dialog 隐藏键盘,android dialog 隐藏虚拟按键
  16. Seaweed-FS综合使用测试
  17. MATALAB绘制色图变换和Voronoi图
  18. int、long和long long的范围
  19. 基于 MVC 模式实现简单 航班查询系统
  20. 从零开始学习CANoe(十一)—— 信号发生器(Signal Generator)

热门文章

  1. 2021-06-29
  2. 生成有控制台的WIN32程序
  3. 彻底弄懂C语言数组名
  4. Windows保护模式学习笔记(十三)—— PWTPCD
  5. 2、(整数类型)INT、TINYINT、SMALLINT、MEDIUMINT、BIGINT
  6. 1.13 空字符串和null的区别
  7. Acwing 第 2场热身赛 【完结】
  8. JDBC之在分层结构中实现业务
  9. Excel的加密和解密
  10. python多重循环导致内存不足_Python多重处理拒绝循环