这篇总结主要是总结下资源的热更新
前段时间闲来无事,狂撸了下项目的热更新代码,写个笔记总结下吧
打包其实比较简单,主要是项目结构的设计和文件目录的处理比较麻烦。
先设计一个文件结构
--ABResource -- 所有资源打包的主目录
//这些目录是资源的大类
--UI -图集,图片icon资源等
--Module1
--Module2
--Module3
-Animation 动画 animator等资源
--Module1
--Module2
--Module3
--Sound 声音资源
--Module1
--Module2
--Module3
--Model 模型资源
--Map 地图资源,场景相关的超级大图
--Effect 特效类
--Audio 视频类
文件结构的设计直接影响后期的开发效率,打包方式流程其实都知道,但是文件目录结构设计的好,对项目的开发效率提升非常大,所有模块对应的子文件夹名字尽量统一,方便开发的时候使用统一命名存取资源。减少逻辑成本!
打包唯一复杂的地方就是文件夹读取,后缀名的转换
关键是对这个结构体字段的理解 AssetBundleBuild
首先,每一个AssetBundleBuild都代表将要生成的一个ab文件
一个ab文件里面可以关联N个资源,至于多少个资源,由AssetBundleBuild里面的assetNames决定,Unity会根据名字找到当前这个文件夹里面的资源,注意这里面的路径都是Unity Asset开始的相对路径,而C#的Path、Directory这些路径获取工具拿到的都是全局路径,需要自己做转换
AssetBundleBuild里面只有2个字段是比较重要的
AssetBundleBuild.assetBundleName --------这个字段决定了你这份ab文件生成的名字
AssetBundleBuild.assetNames --------这个字段决定了你这份ab文件里面包含了多少个资源
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEditor; using System.Linq; using System; public class BundelTest { private static Dictionary<string,AssetBundleBuild> modulAbDic = new Dictionary<string, AssetBundleBuild>(); Dictionary<string,AssetBundle> AllAb = new Dictionary<string, AssetBundle>(); /// <summary> /// 解析每个模块 /// </summary> /// <param name="path"></param> public static void BuildAllBundle(string path) { //这里是采用上述的文件结构,所以做的3层遍历,也可以做成递归的方式,让其适用多个层级 // 判断这个路径是否存在 if (Directory.Exists(path)) { Directory.CreateDirectory(path); } string realPath = Path.Combine(Application.dataPath,path); string[] floderList = Directory.GetDirectories(realPath);//这个只能获取当前层级的子层级,不能获取嵌套的 for (int i = 0; i < floderList.Length; i++) { string[] fileNames = Directory.GetDirectories(floderList[i]);//这个文件夹下的所有的子文件夹 for (int a = 0; a < fileNames.Length; a++) { getBundls(fileNames[a]);//第一层文件夹下面的文件。不包括里面文件夹 } } } /// <summary> /// 解析模块内的资源 /// </summary> /// <param name="path"></param> public static void getBundls(string modulePath) { modulePath = modulePath.Replace("\\","/"); //合并的路径都是\\需要转义 string[] flies = Directory.GetFiles(modulePath); if (flies.Length > 0 ) { for (int i = 0; i < flies.Length; i++) { //处理模块内文件 string assetBundleName = flies[i].Replace(Application.dataPath+"/",""); string ralativePath = getRelativePah(flies[i]); string _abPath =ralativePath; string ext = Path.GetExtension(ralativePath); assetBundleName = assetBundleName.Replace(ext,"")+".ab"; if (ext != ".meta") { string name = Path.GetDirectoryName(ralativePath)+"/"+Path.GetFileNameWithoutExtension(ralativePath); //包的名字,这个名字包含了资源的路径。 AssetBundleBuild build = new AssetBundleBuild() ; if (modulAbDic.ContainsKey(_abPath)) { if (modulAbDic.TryGetValue(_abPath,out build)) { build.assetBundleName = assetBundleName; build.assetNames = new string[]{ralativePath}; --这里是一个资源对应一个build 所以是固定的 modulAbDic[_abPath] = build; } } else { build.assetBundleName = assetBundleName; build.assetNames = new string[]{ralativePath}; modulAbDic.Add(_abPath,build); } } } } } /// <summary> /// 打包所有资源,每个资源打一份ab,方便进行差异化分析 /// </summary> public static void BuildAssetBundleForDic() { AssetBundleBuild[] builds = modulAbDic.Values.ToArray();
//输出路径可以自行选择,这里是默认输出在桌面 BuildPipeline.BuildAssetBundles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory),"bundle"),builds,BuildAssetBundleOptions.DeterministicAssetBundle ,BuildTarget.StandaloneWindows64); } /// <summary> /// 获取asset下的相对位置 /// </summary> public static string getRelativePah(string path) { string _path = path.Replace("\\","/"); return _path.Replace(Application.dataPath,"Assets"); } }