/// <summary> /// 生成AssetBundle /// </summary> /// <param name="outputPath">导出目录</param> /// <param name="target">平台</param> /// <param name="options">打包参数</param> /// <param name="isHashName">是否为hash name</param> public static bool GenAssetBundle(string outputPath, RuntimePlatform platform, BuildTarget target, BuildAssetBundleOptions options = BuildAssetBundleOptions.ChunkBasedCompression, bool isHashName = false, string AES = "") { var _outputPath = Path.Combine(outputPath, BDApplication.GetPlatformPath(platform)); // var artOutputPath = IPath.Combine(_outputPath, "Art"); var buildInfoPath = IPath.Combine(artOutputPath, "BuildInfo.json"); //初始化 allfileHashMap = new Dictionary <string, string>(); var assetPaths = BDApplication.GetAllAssetsPath(); for (int i = 0; i < assetPaths.Count; i++) { assetPaths[i] = assetPaths[i].ToLower(); } /***********************新老资源依赖生成************************/ //获取老的配置 BuildInfo lastBuildInfo = new BuildInfo(); if (File.Exists(buildInfoPath)) { var content = File.ReadAllText(buildInfoPath); lastBuildInfo = JsonMapper.ToObject <BuildInfo>(content); } //获取当前配置 var newbuildInfo = GetAssetsInfo(assetPaths); var buildinfoCahce = JsonMapper.ToJson(newbuildInfo); //BD生命周期触发 BDEditorBehaviorHelper.OnBeginBuildAssetBundle(newbuildInfo); //获取改动的数据 var changedBuildInfo = GetChangedAssets(lastBuildInfo, newbuildInfo); // newbuildInfo = null; //防止后面再用 if (changedBuildInfo.AssetDataMaps.Count == 0) { Debug.Log("无资源改变,不需要打包!"); return(false); } #region 整理依赖关系 //1.把依赖资源替换成AB Name, foreach (var asset in newbuildInfo.AssetDataMaps.Values) { for (int i = 0; i < asset.DependList.Count; i++) { var da = asset.DependList[i]; var dependAssetData = newbuildInfo.AssetDataMaps[da]; //替换成真正AB名 if (!string.IsNullOrEmpty(dependAssetData.ABName)) { asset.DependList[i] = dependAssetData.ABName; } } //去重 asset.DependList = asset.DependList.Distinct().ToList(); asset.DependList.Remove(asset.ABName); } var runtimeStr = "/runtime/"; if (isHashName) { //使用guid 作为ab名 foreach (var asset in newbuildInfo.AssetDataMaps) { var abname = AssetDatabase.AssetPathToGUID(asset.Value.ABName); if (!string.IsNullOrEmpty(abname)) //不存在的资源(如ab.shader之类),则用原名 { asset.Value.ABName = abname; } else { Debug.LogError("获取GUID失败:" + asset.Value.ABName); } for (int i = 0; i < asset.Value.DependList.Count; i++) { var dependAssetName = asset.Value.DependList[i]; abname = AssetDatabase.AssetPathToGUID(dependAssetName); if (!string.IsNullOrEmpty(abname)) //不存在的资源(如ab.shader之类),则用原名 { asset.Value.DependList[i] = abname; } else { Debug.LogError("获取GUID失败:" + dependAssetName); } } } } else { //2.整理runtime路径 替换路径名为Resource规则的名字 foreach (var asset in newbuildInfo.AssetDataMaps) { if (asset.Key.Contains(runtimeStr)) { var newName = asset.Value.ABName; //移除runtime之前的路径、后缀 var index = newName.IndexOf(runtimeStr); newName = newName.Substring(index + 1); //runtimeStr.Length); var extension = Path.GetExtension(newName); if (!string.IsNullOrEmpty(extension)) { newName = newName.Replace(extension, ""); } //刷新整个列表替换 foreach (var _asset in newbuildInfo.AssetDataMaps) { var oldName = asset.Key.ToLower(); //ab替换 if (_asset.Value.ABName == oldName) { _asset.Value.ABName = newName; } //依赖替换 for (int i = 0; i < _asset.Value.DependList.Count; i++) { if (_asset.Value.DependList[i] == oldName) { _asset.Value.DependList[i] = newName; } } } } } } #endregion #region 生成Runtime使用的Config //根据buildinfo 生成加载用的 Config //1.只保留Runtime目录下的配置 ManifestConfig config = new ManifestConfig(); config.IsHashName = isHashName; // foreach (var item in newbuildInfo.AssetDataMaps) { //runtime路径下, //改成用Resources加载规则命名的key if (item.Key.Contains(runtimeStr)) { var key = item.Key; //移除runtime之前的路径、后缀 var index = key.IndexOf(runtimeStr); if (config.IsHashName) { key = key.Substring(index + runtimeStr.Length); //hash要去掉runtime } else { key = key.Substring(index + 1); // 保留runtime } var exten = Path.GetExtension(key); if (!string.IsNullOrEmpty(exten)) { key = key.Replace(exten, ""); } //添加manifest var mi = new ManifestItem(item.Value.ABName, (ManifestItem.AssetTypeEnum)item.Value.Type, new List <string>(item.Value.DependList)); config.ManifestMap[key] = mi; } } //写入 FileHelper.WriteAllText(artOutputPath + "/Config.json", JsonMapper.ToJson(config)); #endregion #region 设置ABname /***********************开始设置build ab************************/ //设置AB name foreach (var changedAsset in changedBuildInfo.AssetDataMaps) { //根据改变的ChangedAssets,获取Asset的资源 var key = changedAsset.Key; var asset = newbuildInfo.AssetDataMaps[changedAsset.Key]; //设置ABName 有ab的则用ab ,没有就用configpath string abname = asset.ABName; // var ai = GetAssetImporter(key); if (ai) { ai.assetBundleName = abname; } } #endregion //3.生成AssetBundle try { BuildAssetBundle(target, _outputPath, options); } catch (Exception e) { Debug.LogException(e); throw; } //4.清除AB Name RemoveAllAssetbundleName(); AssetImpoterCacheMap.Clear(); //the end.删除无用文件 var delFiles = Directory.GetFiles(artOutputPath, "*", SearchOption.AllDirectories); foreach (var df in delFiles) { var ext = Path.GetExtension(df); if (ext == ".meta" || ext == ".manifest") { File.Delete(df); } } //the end. BuildInfo写入 if (File.Exists(buildInfoPath)) { string targetPath = artOutputPath + "/BuildInfo.old.json"; File.Delete(targetPath); File.Move(buildInfoPath, targetPath); } FileHelper.WriteAllText(buildInfoPath, buildinfoCahce); //BD生命周期触发 BDEditorBehaviorHelper.OnEndBuildAssetBundle(outputPath); AssetHelper.AssetHelper.GenPackageBuildInfo(outputPath, platform); return(true); }
/// <summary> /// 生成AssetBundle /// </summary> /// <param name="outPath">导出目录</param> /// <param name="target">平台</param> /// <param name="options">打包参数</param> /// <param name="isHashName">是否为hash name</param> public static void GenAssetBundle(string outPath, BuildTarget target, BuildAssetBundleOptions options = BuildAssetBundleOptions.ChunkBasedCompression, bool isHashName = false, string AES = "") { // var artOutpath = IPath.Combine(outPath, "Art"); var builinfoPath = IPath.Combine(outPath, "BuildInfo.json"); //初始化 allfileHashMap = new Dictionary <string, string>(); var assetPaths = BApplication.GetAllAssetsPath(); for (int i = 0; i < assetPaths.Count; i++) { assetPaths[i] = assetPaths[i].ToLower(); } /***********************新老资源依赖生成************************/ //获取老的配置 BuildInfo lastBuildInfo = new BuildInfo(); if (File.Exists(builinfoPath)) { var content = File.ReadAllText(builinfoPath); lastBuildInfo = JsonMapper.ToObject <BuildInfo>(content); } //获取当前配置 var newbuildInfo = GetAssetsInfo(assetPaths); //获取变动的数据 var changedAssetList = GetChangedAssets(lastBuildInfo, newbuildInfo); if (File.Exists(builinfoPath)) { string targetPath = outPath + "/BuildInfo.old.json"; File.Delete(targetPath); File.Move(builinfoPath, targetPath); } FileHelper.WriteAllText(builinfoPath, JsonMapper.ToJson(newbuildInfo)); /***********************整理依赖关系 减少消耗************************/ //保存buildinfo后, //整理runtime路径,减少加载时候的消耗 var runtimeStr = "/runtime/"; foreach (var asset in newbuildInfo.AssetDataMaps) { if (asset.Value.Name.Contains(runtimeStr)) { var newName = asset.Value.Name; //移除runtime之前的路径 var index = newName.IndexOf(runtimeStr); newName = newName.Substring(index + 1); //runtimeStr.Length); //去除后缀 newName = newName.Replace(Path.GetExtension(newName), ""); //刷新整个列表替换 foreach (var _asset in newbuildInfo.AssetDataMaps) { var oldName = asset.Key.ToLower(); //name替换 if (_asset.Value.Name == oldName) { _asset.Value.Name = newName; } //ab替换 if (_asset.Value.AB == oldName) { _asset.Value.AB = newName; } //依赖替换 for (int i = 0; i < _asset.Value.DependList.Count; i++) { if (_asset.Value.DependList[i] == oldName) { _asset.Value.DependList[i] = newName; } } } } } /***********************生成Config************************/ //根据buildinfo 生成ArtConfig ManifestConfig manifest = new ManifestConfig(); manifest.AES = AES; if (isHashName) { // foreach (var item in newbuildInfo.AssetDataMaps) // { // var dependlist = new List<string>(item.Value.DependList.Count); // for (int i = 0; i < dependlist.Count; i++) // { // var assetName = item.Value.DependList[i]; // // var asset = newbuildInfo.AssetDataMaps[assetName]; // dependlist[i] = asset.Hash; // } // // //添加manifest // var path = !string.IsNullOrEmpty(item.Value.AB) ? item.Value.AB : item.Key; // var mi = new ManifestItem(path, (ManifestItem.AssetTypeEnum) item.Value.Type, dependlist); // configMap[item.Key] = mi; // } } else { foreach (var item in newbuildInfo.AssetDataMaps) { //添加manifest var path = !string.IsNullOrEmpty(item.Value.AB) ? item.Value.AB : item.Value.Name; var mi = new ManifestItem(path, (ManifestItem.AssetTypeEnum)item.Value.Type, new List <string>(item.Value.DependList)); //runtime路径下,改成用Resources加载规则命名的key if (path.StartsWith("runtime/")) { manifest.AddManifest(item.Value.Name, mi); } else { manifest.AddManifest(item.Key, mi); } } } //hash命名 //写入 FileHelper.WriteAllText(artOutpath + "/Config.json", JsonMapper.ToJson(manifest)); /***********************开始设置build ab************************/ //设置AB name foreach (var asset in changedAssetList.AssetDataMaps) { string abname = ""; if (!string.IsNullOrEmpty(asset.Value.AB)) { abname = asset.Value.AB; } else { abname = asset.Value.Name; } var ai = GetAssetImporter(asset.Key); if (ai) { ai.assetBundleName = abname; } } //3.生成AssetBundle BuildAssetBundle(target, outPath, options); //4.清除AB Name RemoveAllAssetbundleName(); AssetImpoterCacheMap.Clear(); //the end.删除无用文件 var delFiles = Directory.GetFiles(artOutpath, "*", SearchOption.AllDirectories); foreach (var df in delFiles) { var ext = Path.GetExtension(df); if (ext == ".meta" || ext == ".manifest") { File.Delete(df); } } }