/// <summary> /// 开始构建AB /// </summary> public void StartBuildAssetBundle(BuildTarget buildTarget) { //-----------------------开始打包AssetBundle逻辑--------------------------- Debug.Log("【BuildAssetbundle】执行Build..."); //设置编辑器状态 BDEditorApplication.EditorStatus = BDFrameworkEditorStatus.BuildAssetBundle; var platform = BApplication.GetRuntimePlatform(buildTarget); var platformOutputPath = IPath.Combine(BuildParams.OutputPath, BApplication.GetPlatformPath(platform)); string abOutputPath = IPath.Combine(platformOutputPath, BResources.ART_ASSET_ROOT_PATH); //--------------------------------开始打包---------------------------------- //1.打包 Debug.Log("<color=green>----->1.进入打包逻辑</color>"); //整理abname this.MergeABName(BuildingAssetInfos); //对比差异文件 var changedAssetsInfo = GetChangedAssets(BuildingAssetInfos, buildTarget); //生成artconfig var assetbundleItemList = this.GenAssetBundleConfig(BuildingAssetInfos, BuildParams, platform); //打包 AssetDatabase.StartAssetEditing(); //禁止自动导入 { this.BuildAssetBundle(assetbundleItemList, changedAssetsInfo, BuildParams, platform); } AssetDatabase.StopAssetEditing(); //恢复自动导入 //2.清理 Debug.Log("<color=green>----->2.清理旧ab</color>"); //移除所有的ab RemoveAllAssetbundleName(); //删除本地没有的资源 var allABList = Directory.GetFiles(abOutputPath, "*", SearchOption.AllDirectories).Where((p) => string.IsNullOrEmpty(Path.GetExtension(p))); foreach (var abpath in allABList) { var abname = Path.GetFileName(abpath); var ret = assetbundleItemList.FirstOrDefault((abdata) => abdata.AssetBundlePath == abname); if (ret == null) { // File.Delete(abpath); File.Delete(abpath + ".manifest"); // var path = AssetDatabase.GUIDToAssetPath(abname); Debug.Log("【删除旧ab:】" + abname + " - " + path); } } //3.BuildInfo配置处理 Debug.Log("<color=green>----->3.BuildInfo相关生成</color>"); //设置ab的hash foreach (var abi in assetbundleItemList) { if (string.IsNullOrEmpty(abi.AssetBundlePath)) { continue; } var abpath = IPath.Combine(platformOutputPath, BResources.ART_ASSET_ROOT_PATH, abi.AssetBundlePath); var hash = FileHelper.GetMurmurHash3(abpath); abi.Hash = hash; } //获取上一次打包的数据,跟这次打包数据合并 var configPath = IPath.Combine(platformOutputPath, BResources.ART_ASSET_CONFIG_PATH); if (File.Exists(configPath)) { var lastAssetbundleItemList = CsvSerializer.DeserializeFromString <List <AssetBundleItem> >(File.ReadAllText(configPath)); foreach (var newABI in assetbundleItemList) { if (string.IsNullOrEmpty(newABI.AssetBundlePath)) { continue; } // //判断是否在当前打包列表中 // var ret = changedAssetsInfo.AssetDataMaps.Values.FirstOrDefault((a) => a.ABName.Equals(newABI.AssetBundlePath, StringComparison.OrdinalIgnoreCase)); var lastABI = lastAssetbundleItemList.FirstOrDefault((last) => newABI.AssetBundlePath.Equals(last.AssetBundlePath, StringComparison.OrdinalIgnoreCase)); //AB名相等 //&& newABI.Hash == last.Hash); //hash相等 //没重新打包,则用上一次的mix信息 if (lastABI != null && lastABI.Hash == newABI.Hash) { newABI.Mix = lastABI.Mix; } //否则mix = 0 } } //保存artconfig.info var csv = CsvSerializer.SerializeToString(assetbundleItemList); FileHelper.WriteAllText(configPath, csv); //保存BuildInfo配置 var buildinfoPath = IPath.Combine(platformOutputPath, BResources.EDITOR_ART_ASSET_BUILD_INFO_PATH); //缓存buildinfo var json = JsonMapper.ToJson(BuildingAssetInfos, true); FileHelper.WriteAllText(buildinfoPath, json); //4.备份Artifacts //this.BackupArtifacts(buildTarget); //5.检测本地的Manifest和构建预期对比 Debug.Log("<color=green>----->5.校验AB依赖</color>"); var abRootPath = IPath.Combine(BuildParams.OutputPath, BApplication.GetPlatformPath(platform), BResources.ART_ASSET_ROOT_PATH); var previewABUnitMap = BuildingAssetInfos.PreviewAssetbundleUnit(); var manifestList = Directory.GetFiles(abRootPath, "*.manifest", SearchOption.AllDirectories); //解析 manifestBuildParams.OutputPath for (int i = 0; i < manifestList.Length; i++) { var manifest = manifestList[i].Replace("\\", "/"); if (manifest.Equals(abRootPath + ".manifest")) { continue; } var lines = File.ReadLines(manifest); List <string> manifestDependList = new List <string>(); bool isStartRead = false; foreach (var line in lines) { if (!isStartRead && line.Equals("Assets:")) { isStartRead = true; } else if (line.Contains("Dependencies:")) { break; } else if (isStartRead) { var file = line.Replace("- ", ""); manifestDependList.Add(file.ToLower()); } } //对比依赖 var abname = Path.GetFileNameWithoutExtension(manifest); if (abname.Equals(BResources.ART_ASSET_ROOT_PATH, StringComparison.OrdinalIgnoreCase)) { continue; } previewABUnitMap.TryGetValue(abname, out var previewABDependList); if (previewABDependList == null) { Debug.LogError("【AssetbundleV2-验证】本地ab的配置不不存在:" + abname); Debug.LogError("path:" + AssetDatabase.GUIDToAssetPath(abname)); } else { //求差集 var except = manifestDependList.Except(previewABDependList); if (except.Count() != 0) { var local = JsonMapper.ToJson(manifestDependList, true); var preview = JsonMapper.ToJson(previewABDependList, true); Debug.LogError($"【AssetbundleV2-验证】本地AssetBundle依赖与预期不符:\n 本地:{local} \n 预期:{preview}"); } } } //6.资源混淆 Debug.Log("<color=green>----->6.混淆AB</color>"); if (BDEditorApplication.BDFrameworkEditorSetting.BuildAssetBundleSetting.IsEnableObfuscation) { AssetBundleEditorToolsV2.MixAssetBundle(BuildParams.OutputPath, platform); } //恢复编辑器状态 BDEditorApplication.EditorStatus = BDFrameworkEditorStatus.Idle; //BD生命周期触发 BDFrameworkPipelineHelper.OnEndBuildAssetBundle(this); //GenAssetBundleItemCacheList = abConfigList.ToList(); }