/// <summary> /// 创建存储的名字 /// 主要是用于 Runtime下和Runtime外的区分 /// </summary> /// <param name="str"></param> /// <returns></returns> static public string CheckAssetSaveInfo(string str, ref ManifestItem.AssetTypeEnum @typeEnum) { //判断类型 var ext = Path.GetExtension(str).ToLower(); if (ext.Equals(".prefab")) { typeEnum = ManifestItem.AssetTypeEnum.Prefab; } else if (ext.Equals(".spriteatlas")) { typeEnum = ManifestItem.AssetTypeEnum.SpriteAtlas; } else { typeEnum = ManifestItem.AssetTypeEnum.Others; } //判断是否在Runtime中 //Runtime中要掐头去尾 if (str.StartsWith("Assets/Resource/Runtime/")) { str = str.Replace("Assets/Resource/Runtime/", ""); if (!string.IsNullOrEmpty(ext)) { str = str.Replace(ext, ""); } } return(str); }
/// <summary> /// 添加一个依赖,这个仅在Editor下调用 /// </summary> /// <param name="name"></param> /// <param name="dependencies"></param> public void AddItem(string name, string hash, List <string> dependencies, ManifestItem.AssetTypeEnum @enum, string packageName = "") { ManifestItem item = null; if (this.Manifest_NameKey.TryGetValue(name, out item)) { if (item.Hash != hash) { Debug.LogError("有重名:" + name + ",如无显式BResource.Load加载则无视,隐式会自动根据hash算依赖!"); name = name + "_r"; item = new ManifestItem(name, hash, packageName, @enum, dependencies); this.Manifest_NameKey[name] = item; this.Manifest_HashKey[hash] = item; } else if (dependencies.Count >= item.Depend.Count) { item = new ManifestItem(name, hash, packageName, @enum, dependencies); this.Manifest_NameKey[name] = item; this.Manifest_HashKey[hash] = item; } } else { item = new ManifestItem(name, hash, packageName, @enum, dependencies); this.Manifest_NameKey[name] = item; this.Manifest_HashKey[hash] = item; } }
/// <summary> /// 创建存储的名字 /// 主要是用于 Runtime下和Runtime外的区分 /// </summary> /// <param name="str"></param> /// <returns></returns> static public string CheckAssetSaveInfo(string str, ref ManifestItem.AssetTypeEnum @typeEnum) { //判断类型 var ext = Path.GetExtension(str).ToLower(); if (ext.Equals(".prefab")) { typeEnum = ManifestItem.AssetTypeEnum.Prefab; } else if (ext.Equals(".spriteatlas")) { typeEnum = ManifestItem.AssetTypeEnum.SpriteAtlas; } else { typeEnum = ManifestItem.AssetTypeEnum.Others; } //判断是否在Runtime中 //Runtime中要掐头去尾 var findStr = "/Runtime/"; if (str.Contains(findStr)) { var index = str.IndexOf(findStr); str = str.Substring(index + findStr.Length); // if (!string.IsNullOrEmpty(ext)) { str = str.Replace(ext, ""); } } return(str); }
/// <summary> /// 分析资源 /// </summary> /// <param name="paths"></param> /// <param name="target"></param> /// <param name="outpath"></param> private static void AnalyzeResource(string[] paths, BuildTarget target, string outpath) { additionBuildPackageCache = new List <string>(); CurManifestConfig = new ManifestConfig(); //以下三个建议使用内部函数,不要直接调用unity原生接口获取, allfileHashMap = new Dictionary <string, string>(); //file hash获取缓存 assetImpoterMap = new Dictionary <string, AssetImporter>(); //Assetimport获取缓存 DependenciesMap = new Dictionary <string, List <string> >(); //依赖获取缓存 //加载配置 ManifestConfig lastManifestConfig = null; if (File.Exists(configPath)) { lastManifestConfig = new ManifestConfig(File.ReadAllText(configPath)); } else { lastManifestConfig = new ManifestConfig(); } // /***************************************开始分析资源****************************************/ //1.收集图集信息 EditorUtility.DisplayProgressBar("分析资源", "收集SpriteAtlas", 0); GetSpriteAtlasInfo(); //2.收集单ab多资源信息 GetBuildAbConfig(); //3.开始分析资源 bool isAdditionBuild = allfileHashMap.Count > 0; //是否为增量打包 List <string> changeList = new List <string>(); for (int index = 0; index < paths.Length; index++) { var mainAssetFullPath = paths[index].Replace("\\", "/"); EditorUtility.DisplayProgressBar("分析资源", string.Format("分析:{0} {1}/{2}", Path.GetFileName(mainAssetFullPath), index + 1, paths.Length), (index + 1f) / paths.Length); //获取被依赖的路径 var mainAssetPath = "Assets" + mainAssetFullPath.Replace(Application.dataPath, ""); var subAssetsPath = GetDependencies(mainAssetPath).ToList(); List <string> subAssetHashList = new List <string>(); //处理依赖资源打包 for (int i = 0; i < subAssetsPath.Count; i++) { var subAsset = subAssetsPath[i]; var subAssetPath = subAssetsPath[i];// Application.dataPath + subAsset.Replace("Assets/", "/"); string subAssetHash = GetHashFromFile(subAssetPath); subAssetHashList.Add(subAssetHash); //本地ab文件存在则不打包 var localABPath = IPath.Combine(outpath, subAssetHash); if (File.Exists(localABPath)) { var lastItem = lastManifestConfig.GetManifestItemByHash(subAssetHash); if (lastItem != null) { CurManifestConfig.AddItem(lastItem); continue; } } else { // 需要对比之前的hash var lastItem = lastManifestConfig.GetManifestItemByHash(subAssetHash); if (lastItem != null && lastItem.Package != "" && lastItem.Hash == subAssetHash) { CurManifestConfig.AddItem(lastItem); continue; } } #region 嵌套引用 - 缓存 var subAssetDpendList = GetDependencies(subAsset).ToList(); //sub dpend 2 hash if (subAssetDpendList.Count > 1) { for (int j = 0; j < subAssetDpendList.Count; j++) { var sbd = subAssetDpendList[j];// Application.dataPath + subAssetDpendList[j].Replace("Assets/", "/"); subAssetDpendList[j] = GetHashFromFile(sbd); } } else { subAssetDpendList.Clear(); } #endregion //开始设置abname var ai = GetAssetImporter(subAsset); ManifestItem.AssetTypeEnum @enum = ManifestItem.AssetTypeEnum.Others; var savename = CheckAssetSaveInfo(subAsset, ref @enum); string packageHashName = null; #region 单ab多资源模式 if (IsMakePackage(subAsset, ref packageHashName)) { #region 增量打包遇到单ab多资源 //增量打包时,如果遇到多包合一时,其中某个变动,剩余的也要一次性打出 // if (isAdditionBuild && !additionBuildPackageCache.Contains(packageHashName)) // { // var lastAssets = lastManifestConfig.Manifest_NameKey.Values.ToList().FindAll((item) => // !string.IsNullOrEmpty(item.Package) && item.Package == packageHashName); // foreach (var la in lastAssets) // { // //考虑增量打包时候,得补齐Runtime下的路径名 // var path = la.Name; // if (!path.StartsWith("Assets/")) // { // foreach (var key in LastAllAssetCache.Keys) // { // var p = path + "."; // if (key.Contains(p)) // { // path = key; // } // } // } // // //获取上次的importer // var laAI = GetAssetImporter(path); // if (laAI == null) // { // Debug.LogError("资源不存在:" + la.Name); // continue; // } // // laAI.assetBundleName = packageHashName; // laAI.assetBundleVariant = ""; // } // // if (isAdditionBuild) // { // additionBuildPackageCache.Add(packageHashName); // } // } #endregion string packageName = ""; foreach (var item in allfileHashMap) { if (item.Value == packageHashName) { packageName = item.Key; packageName = packageName.Replace(BApplication.ProjectRoot + "/", ""); break; } } //保存配置 if (subAsset != mainAssetPath) { CurManifestConfig.AddItem(savename, subAssetHash, subAssetDpendList, @enum, packageHashName); } ai.assetBundleName = packageName; ai.assetBundleVariant = ""; // ai.assetBundleName = packageHashName; // ai.assetBundleVariant = ""; } #endregion #region 单ab单资源模式 else { if (subAsset != mainAssetPath) { CurManifestConfig.AddItem(savename, subAssetHash, subAssetDpendList, @enum); } // if (!subAsset.Contains("Assets/")) // { // ai.assetBundleName = "Assets/Resource/Runtime/" + savename; // ai.assetBundleVariant = ""; // } // else // { ai.assetBundleName = subAsset; ai.assetBundleVariant = ""; // } // ai.assetBundleName = subAssetHash; // ai.assetBundleVariant = ""; } #endregion changeList.Add(subAsset); } //最后保存主文件 var mainHash = GetHashFromFile(mainAssetPath); string package = null; subAssetHashList.Remove(mainHash); if (IsMakePackage(mainAssetPath, ref package)) { //单ab包-多资源模式 ManifestItem.AssetTypeEnum @enum = ManifestItem.AssetTypeEnum.Others; var sn = CheckAssetSaveInfo(mainAssetPath, ref @enum); CurManifestConfig.AddItem(sn, mainHash, subAssetHashList, @enum, package); } else { //单ab包-单资源模式 ManifestItem.AssetTypeEnum @enum = ManifestItem.AssetTypeEnum.Others; var sn = CheckAssetSaveInfo(mainAssetPath, ref @enum); CurManifestConfig.AddItem(sn, mainHash, subAssetHashList, @enum); } } //补全 [单ab多资源的配置],并将真正的hash传入 foreach (var con in PackageConfig) { var hash = GetHashFromString(con.AssetBundleName); //多合一ab的hash是要有所有的依赖文件 hash,再hash一次 CurManifestConfig.AddItem(con.AssetBundleName, hash, new List <string>(), ManifestItem.AssetTypeEnum.Others); } //最后检查配置 foreach (var item in CurManifestConfig.Manifest_HashKey.Values) { for (int i = 0; i < item.Depend.Count; i++) { var dHash = item.Depend[i]; //判断是否在runtime内 var dItem = CurManifestConfig.GetManifestItemByHash(dHash); if (dItem != null) { if (!string.IsNullOrEmpty(dItem.Package)) { //将非Runtime目录中的 item.Depend[i] = dItem.Package; } } else { Debug.LogError("【资源遗失】没找到依赖项:" + dHash); foreach (var v in allfileHashMap) { if (dHash == v.Value) { Debug.LogError("hash source file:" + v.Key); break; } } } } item.Depend.Remove(item.Hash); item.Depend = item.Depend.Distinct().ToList(); } EditorUtility.ClearProgressBar(); changeList = changeList.Distinct().ToList(); Debug.LogFormat("<color=red>本地需要打包数量:{0}</color>", changeList.Count); var buildpath = string.Format("{0}/{1}_changelist.json", Application.streamingAssetsPath, target.ToString()); File.WriteAllText(buildpath, JsonMapper.ToJson(changeList)); Debug.Log("本地打包保存:" + buildpath); }