/// <summary> /// write manifest into target path. /// </summary> static void WriteManifestFile(string path, IBundleBuildResults bundleResults, BuildTarget target, string remoteURL) { var manifest = new AssetbundleBuildManifest(); manifest.BuildTarget = target.ToString(); //we use unity provided dependency result for final check var deps = bundleResults.BundleInfos.ToDictionary(kv => kv.Key, kv => kv.Value.Dependencies.ToList()); foreach (var result in bundleResults.BundleInfos) { var bundleInfo = new AssetbundleBuildManifest.BundleInfo(); bundleInfo.BundleName = result.Key; bundleInfo.Dependencies = Utility.CollectBundleDependencies(deps, result.Key); bundleInfo.Hash = result.Value.Hash; bundleInfo.Size = new FileInfo(result.Value.FileName).Length; manifest.BundleInfos.Add(bundleInfo); } //sort by size manifest.BundleInfos.Sort((a, b) => b.Size.CompareTo(a.Size)); var manifestString = JsonUtility.ToJson(manifest); manifest.GlobalHash = Hash128.Compute(manifestString); manifest.BuildTime = DateTime.UtcNow.Ticks; manifest.RemoteURL = remoteURL; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } File.WriteAllText(Utility.CombinePath(path, AssetbundleBuildSettings.ManifestFileName), JsonUtility.ToJson(manifest, true)); }
/// <summary> /// write logs into target path. /// </summary> static void WriteLogFile(string path, IBundleBuildResults bundleResults) { var sb = new System.Text.StringBuilder(); sb.AppendLine($"Build Time : {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}"); sb.AppendLine(); for (int i = 0; i < bundleResults.BundleInfos.Count; i++) { var bundleInfo = bundleResults.BundleInfos.ElementAt(i); var writeResult = bundleResults.WriteResults.ElementAt(i); sb.AppendLine($"----File Path : {bundleInfo.Value.FileName}----"); var assetDic = new Dictionary <string, ulong>(); foreach (var file in writeResult.Value.serializedObjects) { //skip nonassettype if (file.serializedObject.fileType == UnityEditor.Build.Content.FileType.NonAssetType) { continue; } //gather size var assetPath = AssetDatabase.GUIDToAssetPath(file.serializedObject.guid.ToString()); if (!assetDic.ContainsKey(assetPath)) { assetDic.Add(assetPath, file.header.size); } else { assetDic[assetPath] += file.header.size; } } //sort by it's size var sortedAssets = assetDic.OrderByDescending(kv => kv.Value).ThenBy(kv => kv.Key); foreach (var asset in sortedAssets) { sb.AppendLine($"{(asset.Value * 0.000001f).ToString("0.00000").PadLeft(10)} mb - {asset.Key}"); } sb.AppendLine(); } if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } File.WriteAllText(Path.Combine(path, LogFileName), sb.ToString()); }
public static string Generate(AssetbundleBuildSettings settings, IBundleBuildResults result) { var linkGenerator = new LinkXmlGenerator(); foreach (var writeResult in result.WriteResults) { linkGenerator.AddTypes(writeResult.Value.includedTypes); } var settingsPath = Application.dataPath.Remove(Application.dataPath.Length - 6) + AssetDatabase.GetAssetPath(settings); settingsPath = settingsPath.Remove(settingsPath.LastIndexOf('/')); var linkPath = $"{settingsPath}/link.xml"; linkGenerator.Save(linkPath); AssetDatabase.Refresh(); return(linkPath.Remove(0, Application.dataPath.Length - 6)); }
void PostProcessBundles(AddressableAssetGroup assetGroup, List <string> buildBundles, List <string> outputBundles, IBundleBuildResults buildResult, IWriteData writeData, ResourceManagerRuntimeData runtimeData, List <ContentCatalogDataEntry> locations, FileRegistry registry, Dictionary <string, ContentCatalogDataEntry> primaryKeyToCatalogEntry) { var schema = assetGroup.GetSchema <BundledAssetGroupSchema>(); if (schema == null) { return; } var path = schema.BuildPath.GetValue(assetGroup.Settings); if (string.IsNullOrEmpty(path)) { return; } for (int i = 0; i < buildBundles.Count; ++i) { if (primaryKeyToCatalogEntry.TryGetValue(buildBundles[i], out ContentCatalogDataEntry dataEntry)) { var info = buildResult.BundleInfos[buildBundles[i]]; var requestOptions = new AssetBundleRequestOptions { Crc = schema.UseAssetBundleCrc ? info.Crc : 0, Hash = schema.UseAssetBundleCache ? info.Hash.ToString() : "", ChunkedTransfer = schema.ChunkedTransfer, RedirectLimit = schema.RedirectLimit, RetryCount = schema.RetryCount, Timeout = schema.Timeout, BundleName = Path.GetFileName(info.FileName), BundleSize = GetFileSize(info.FileName) }; dataEntry.Data = requestOptions; int extensionLength = Path.GetExtension(outputBundles[i]).Length; string[] deconstructedBundleName = outputBundles[i].Substring(0, outputBundles[i].Length - extensionLength).Split('_'); string reconstructedBundleName = string.Join("_", deconstructedBundleName, 1, deconstructedBundleName.Length - 1) + ".bundle"; outputBundles[i] = ConstructAssetBundleName(assetGroup, schema, info, reconstructedBundleName); dataEntry.InternalId = dataEntry.InternalId.Remove(dataEntry.InternalId.Length - buildBundles[i].Length) + outputBundles[i]; dataEntry.Keys[0] = outputBundles[i]; ReplaceDependencyKeys(buildBundles[i], outputBundles[i], locations); if (!m_BundleToInternalId.ContainsKey(buildBundles[i])) { m_BundleToInternalId.Add(buildBundles[i], dataEntry.InternalId); } if (dataEntry.InternalId.StartsWith("http:\\")) { dataEntry.InternalId = dataEntry.InternalId.Replace("http:\\", "http://").Replace("\\", "/"); } if (dataEntry.InternalId.StartsWith("https:\\")) { dataEntry.InternalId = dataEntry.InternalId.Replace("https:\\", "https://").Replace("\\", "/"); } } else { Debug.LogWarningFormat("Unable to find ContentCatalogDataEntry for bundle {0}.", outputBundles[i]); } var targetPath = Path.Combine(path, outputBundles[i]); if (!Directory.Exists(Path.GetDirectoryName(targetPath))) { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); } File.Copy(Path.Combine(assetGroup.Settings.buildSettings.bundleBuildPath, buildBundles[i]), targetPath, true); registry.AddFile(targetPath); } }
public BuildResult(ReturnCode exitCode, IBundleBuildResults bundleBuildResults) { ExitCode = exitCode; BundleBuildResults = bundleBuildResults; }
static void PostProcessBundles(AddressableAssetGroup assetGroup, List <string> bundles, IBundleBuildResults buildResult, IWriteData writeData, ResourceManagerRuntimeData runtimeData, List <ContentCatalogDataEntry> locations, FileRegistry registry) { var schema = assetGroup.GetSchema <BundledAssetGroupSchema>(); if (schema == null) { return; } var path = schema.BuildPath.GetValue(assetGroup.Settings); if (string.IsNullOrEmpty(path)) { return; } foreach (var originalBundleName in bundles) { var newBundleName = originalBundleName; var info = buildResult.BundleInfos[newBundleName]; ContentCatalogDataEntry dataEntry = locations.FirstOrDefault(s => newBundleName == (string)s.Keys[0]); if (dataEntry != null) { var requestOptions = new AssetBundleRequestOptions { Crc = schema.UseAssetBundleCrc ? info.Crc : 0, Hash = schema.UseAssetBundleCache ? info.Hash.ToString() : "", ChunkedTransfer = schema.ChunkedTransfer, RedirectLimit = schema.RedirectLimit, RetryCount = schema.RetryCount, Timeout = schema.Timeout, BundleName = Path.GetFileName(info.FileName), BundleSize = GetFileSize(info.FileName) }; dataEntry.Data = requestOptions; dataEntry.InternalId = BuildUtility.GetNameWithHashNaming(schema.BundleNaming, info.Hash.ToString(), dataEntry.InternalId); newBundleName = BuildUtility.GetNameWithHashNaming(schema.BundleNaming, info.Hash.ToString(), newBundleName); } else { Debug.LogWarningFormat("Unable to find ContentCatalogDataEntry for bundle {0}.", newBundleName); } var targetPath = Path.Combine(path, newBundleName); if (!Directory.Exists(Path.GetDirectoryName(targetPath))) { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); } File.Copy(Path.Combine(assetGroup.Settings.buildSettings.bundleBuildPath, originalBundleName), targetPath, true); registry.AddFile(targetPath); } }
/// <summary> /// Default implementation of generating Asset Bundles using the Scriptable Build Pipeline. /// </summary> /// <param name="parameters">Set of parameters used for building asset bundles.</param> /// <param name="content">Set of content and explicit asset bundle layout to build.</param> /// <param name="result">Results from building the content and explicit asset bundle layout.</param> /// <param name="taskList">Custom task list for building asset bundles.</param> /// <param name="contextObjects">Additional context objects to make available to the build.</param> /// <returns>Return code with status information about success or failure causes.</returns> public static ReturnCode BuildAssetBundles(IBundleBuildParameters parameters, IBundleBuildContent content, out IBundleBuildResults result, IList <IBuildTask> taskList, params IContextObject[] contextObjects) { // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (parameters == null) { result = null; BuildLogger.LogException(new ArgumentNullException("parameters")); return(ReturnCode.Exception); } // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (taskList.IsNullOrEmpty()) { result = null; BuildLogger.LogException(new ArgumentException("Argument cannot be null or empty.", "taskList")); return(ReturnCode.Exception); } // Don't run if there are unsaved changes if (ValidationMethods.HasDirtyScenes()) { result = null; return(ReturnCode.UnsavedChanges); } AssetDatabase.SaveAssets(); ReturnCode exitCode; result = new BundleBuildResults(); // using (new SceneStateCleanup()) using (new BuildInterfacesWrapper()) using (var progressTracker = new ProgressTracker()) using (var buildCache = new BuildCache(parameters.CacheServerHost, parameters.CacheServerPort)) { Directory.CreateDirectory(parameters.TempOutputFolder); BuildContext buildContext; try { buildContext = new BuildContext(contextObjects); buildContext.SetContextObject(parameters); buildContext.SetContextObject(content); buildContext.SetContextObject(result); buildContext.SetContextObject(progressTracker); buildContext.SetContextObject(buildCache); buildContext.SetContextObject(new Unity5PackedIdentifiers()); buildContext.SetContextObject(new BuildDependencyData()); buildContext.SetContextObject(new BundleWriteData()); buildContext.SetContextObject(BuildCallbacks); } catch (Exception e) { // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code result = null; BuildLogger.LogException(e); return(ReturnCode.Exception); } exitCode = BuildTasksRunner.Validate(taskList, buildContext); if (exitCode >= ReturnCode.Success) { exitCode = BuildTasksRunner.Run(taskList, buildContext); } if (Directory.Exists(parameters.TempOutputFolder)) { Directory.Delete(parameters.TempOutputFolder, true); } } return(exitCode); }
/// <summary> /// Default implementation of generating Asset Bundles using the Scriptable Build Pipeline. /// </summary> /// <param name="parameters">Set of parameters used for building asset bundles.</param> /// <param name="content">Set of content and explicit asset bundle layout to build.</param> /// <param name="result">Results from building the content and explicit asset bundle layout.</param> /// <returns>Return code with status information about success or failure causes.</returns> public static ReturnCode BuildAssetBundles(IBundleBuildParameters parameters, IBundleBuildContent content, out IBundleBuildResults result) { var taskList = DefaultBuildTasks.Create(DefaultBuildTasks.Preset.AssetBundleCompatible); return(BuildAssetBundles(parameters, content, out result, taskList)); }
static void PostProcessBundles(AddressableAssetGroup assetGroup, List <string> bundles, IBundleBuildResults buildResult, IWriteData writeData, ResourceManagerRuntimeData runtimeData, List <ContentCatalogDataEntry> locations, FileRegistry registry) { var schema = assetGroup.GetSchema <BundledAssetGroupSchema>(); if (schema == null) { return; } var path = schema.BuildPath.GetValue(assetGroup.Settings); if (string.IsNullOrEmpty(path)) { return; } foreach (var originalBundleName in bundles) { var newBundleName = originalBundleName; var info = buildResult.BundleInfos[newBundleName]; ContentCatalogDataEntry dataEntry = locations.FirstOrDefault(s => newBundleName == (string)s.Keys[0]); if (dataEntry != null) { var requestOptions = new AssetBundleRequestOptions { Crc = schema.UseAssetBundleCrc ? info.Crc : 0, Hash = schema.UseAssetBundleCache ? info.Hash.ToString() : "", ChunkedTransfer = schema.ChunkedTransfer, RedirectLimit = schema.RedirectLimit, RetryCount = schema.RetryCount, Timeout = schema.Timeout, BundleName = Path.GetFileName(info.FileName), BundleSize = GetFileSize(info.FileName) }; dataEntry.Data = requestOptions; int extensionLength = Path.GetExtension(originalBundleName).Length; string[] deconstructedBundleName = originalBundleName.Substring(0, originalBundleName.Length - extensionLength) .Split('_'); deconstructedBundleName[0] = assetGroup.Name .Replace(" ", "") .Replace('\\', '/') .Replace("//", "/") .ToLower(); string reconstructedBundleName = string.Join("_", deconstructedBundleName) + ".bundle"; newBundleName = BuildUtility.GetNameWithHashNaming(schema.BundleNaming, info.Hash.ToString(), reconstructedBundleName); dataEntry.InternalId = dataEntry.InternalId.Remove(dataEntry.InternalId.Length - originalBundleName.Length) + newBundleName; if (dataEntry.InternalId.StartsWith("http:\\")) { dataEntry.InternalId = dataEntry.InternalId.Replace("http:\\", "http://").Replace("\\", "/"); } } else { Debug.LogWarningFormat("Unable to find ContentCatalogDataEntry for bundle {0}.", newBundleName); } var targetPath = Path.Combine(path, newBundleName); if (!Directory.Exists(Path.GetDirectoryName(targetPath))) { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); } File.Copy(Path.Combine(assetGroup.Settings.buildSettings.bundleBuildPath, originalBundleName), targetPath, true); registry.AddFile(targetPath); } }
/// <summary> /// Default implementation of generating Asset Bundles using the Scriptable Build Pipeline. /// </summary> /// <param name="parameters">Set of parameters used for building asset bundles.</param> /// <param name="content">Set of content and explicit asset bundle layout to build.</param> /// <param name="result">Results from building the content and explicit asset bundle layout.</param> /// <param name="taskList">Custom task list for building asset bundles.</param> /// <param name="contextObjects">Additional context objects to make available to the build.</param> /// <returns>Return code with status information about success or failure causes.</returns> public static ReturnCode BuildAssetBundles(IBundleBuildParameters parameters, IBundleBuildContent content, out IBundleBuildResults result, IList <IBuildTask> taskList, params IContextObject[] contextObjects) { // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (parameters == null) { result = null; BuildLogger.LogException(new ArgumentNullException("parameters")); return(ReturnCode.Exception); } // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (taskList.IsNullOrEmpty()) { result = null; BuildLogger.LogException(new ArgumentException("Argument cannot be null or empty.", "taskList")); return(ReturnCode.Exception); } // Don't run if there are unsaved changes if (ValidationMethods.HasDirtyScenes()) { result = null; return(ReturnCode.UnsavedChanges); } AssetDatabase.SaveAssets(); ReturnCode exitCode; result = new BundleBuildResults(); using (new BuildInterfacesWrapper()) #if !CI_TESTRUNNER_PROJECT using (new SceneStateCleanup()) using (var progressTracker = new ProgressTracker()) #else using (var progressTracker = new ProgressLoggingTracker()) #endif using (var buildCache = new BuildCache(parameters.CacheServerHost, parameters.CacheServerPort)) { Directory.CreateDirectory(parameters.TempOutputFolder); BuildContext buildContext; try { buildContext = new BuildContext(contextObjects); buildContext.SetContextObject(parameters); buildContext.SetContextObject(content); buildContext.SetContextObject(result); buildContext.SetContextObject(progressTracker); buildContext.SetContextObject(buildCache); // If IDeterministicIdentifiers was passed in with contextObjects, don't add the default if (!buildContext.ContainsContextObject(typeof(IDeterministicIdentifiers))) { buildContext.SetContextObject(new Unity5PackedIdentifiers()); } buildContext.SetContextObject(new BuildDependencyData()); buildContext.SetContextObject(new BundleWriteData()); buildContext.SetContextObject(BuildCallbacks); } catch (Exception e) { // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code result = null; BuildLogger.LogException(e); return(ReturnCode.Exception); } exitCode = BuildTasksRunner.Validate(taskList, buildContext); if (exitCode >= ReturnCode.Success) #if SBP_PROFILER_ENABLE { exitCode = BuildTasksRunner.RunProfiled(taskList, buildContext); } #else { exitCode = BuildTasksRunner.Run(taskList, buildContext); } #endif if (Directory.Exists(parameters.TempOutputFolder)) { Directory.Delete(parameters.TempOutputFolder, true); } } int maximumSize = EditorPrefs.GetInt("BuildCache.maximumSize", 200); long maximumCacheSize = maximumSize * 1073741824L; // gigabytes to bytes ThreadPool.QueueUserWorkItem(PruneCache, maximumCacheSize); return(exitCode); }
/// <summary> /// The BundleBuildContent class contains information about all of the Assets you want to build into the BuildMap /// Assets are referenced to by a GUID object, and the Addresses can be obtained and modified by using a GUID to /// refer to each asset and identify its Address /// </summary> /// <param name="outputPath"></param> /// <param name="compressionMode"></param> /// <param name="buildTarget"></param> /// <param name="buildGroup"></param> /// <param name="results"></param> /// <returns></returns> public static ReturnCode BuildAssetBundles(string outputPath, CompressionType compressionMode, BuildTarget buildTarget, BuildTargetGroup buildGroup, out IBundleBuildResults results) { BundleBuildContent buildContent = new BundleBuildContent(ContentBuildInterface.GenerateAssetBundleBuilds()); // Go through assets content and set their address to its filename for (int i = 0; i < buildContent.Assets.Count; ++i) { GUID g = buildContent.Assets[i]; // Get the current address as the full filepath and change it to just be the filename buildContent.Addresses[g] = Path.GetFileNameWithoutExtension(buildContent.Addresses[g]); } BundleBuildParameters buildParams = new BundleBuildParameters(buildTarget, buildGroup, outputPath); switch (compressionMode) { case CompressionType.None: buildParams.BundleCompression = BuildCompression.Uncompressed; break; case CompressionType.Lz4: buildParams.BundleCompression = BuildCompression.LZ4; break; default: buildParams.BundleCompression = BuildCompression.LZMA; break; } return(ContentPipeline.BuildAssetBundles(buildParams, buildContent, out results)); }
internal LegacyAssetBundleManifest(IBundleBuildResults results) { m_Details = new Dictionary <string, BundleDetails>(results.BundleInfos); }
/// <summary> /// Default implementation of generating Asset Bundles using the Scriptable Build Pipeline. /// </summary> /// <param name="parameters">Set of parameters used for building asset bundles.</param> /// <param name="content">Set of content and explicit asset bundle layout to build.</param> /// <param name="result">Results from building the content and explicit asset bundle layout.</param> /// <param name="taskList">Custom task list for building asset bundles.</param> /// <param name="contextObjects">Additional context objects to make available to the build.</param> /// <returns>Return code with status information about success or failure causes.</returns> public static ReturnCode BuildAssetBundles(IBundleBuildParameters parameters, IBundleBuildContent content, out IBundleBuildResults result, IList <IBuildTask> taskList, params IContextObject[] contextObjects) { if (BuildPipeline.isBuildingPlayer) { result = null; BuildLogger.LogException(new InvalidOperationException("Cannot build asset bundles while a build is in progress")); return(ReturnCode.Exception); } // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (parameters == null) { result = null; BuildLogger.LogException(new ArgumentNullException("parameters")); return(ReturnCode.Exception); } // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code if (taskList.IsNullOrEmpty()) { result = null; BuildLogger.LogException(new ArgumentException("Argument cannot be null or empty.", "taskList")); return(ReturnCode.Exception); } // Don't run if there are unsaved changes if (ValidationMethods.HasDirtyScenes()) { result = null; return(ReturnCode.UnsavedChanges); } ThreadingManager.WaitForOutstandingTasks(); BuildContext buildContext = new BuildContext(contextObjects); BuildLog buildLog = null; IBuildLogger logger; if (!buildContext.TryGetContextObject <IBuildLogger>(out logger)) { logger = buildLog = new BuildLog(); buildContext.SetContextObject(buildLog); } using (logger.ScopedStep(LogLevel.Info, "AssetDatabase.SaveAssets")) AssetDatabase.SaveAssets(); ReturnCode exitCode; result = new BundleBuildResults(); BuildCacheUtility.ClearCacheHashes(); using (var interfacesWrapper = new BuildInterfacesWrapper()) #if !CI_TESTRUNNER_PROJECT using (new SceneStateCleanup()) using (var progressTracker = new ProgressTracker()) #else using (var progressTracker = new ProgressLoggingTracker()) #endif using (var buildCache = new BuildCache(parameters.CacheServerHost, parameters.CacheServerPort)) { Directory.CreateDirectory(parameters.TempOutputFolder); Directory.CreateDirectory(parameters.ScriptOutputFolder); try { buildContext.SetContextObject(parameters); buildContext.SetContextObject(content); buildContext.SetContextObject(result); buildContext.SetContextObject(interfacesWrapper); buildContext.SetContextObject(progressTracker); buildContext.SetContextObject(buildCache); // If IDeterministicIdentifiers was passed in with contextObjects, don't add the default if (!buildContext.ContainsContextObject(typeof(IDeterministicIdentifiers))) { buildContext.SetContextObject(parameters.ContiguousBundles ? new PrefabPackedIdentifiers() : (IDeterministicIdentifiers) new Unity5PackedIdentifiers()); } buildContext.SetContextObject(new BuildDependencyData()); buildContext.SetContextObject(new BundleWriteData()); buildContext.SetContextObject(BuildCallbacks); buildCache.SetBuildLogger(logger); } catch (Exception e) { // Avoid throwing exceptions in here as we don't want them bubbling up to calling user code result = null; BuildLogger.LogException(e); return(ReturnCode.Exception); } exitCode = BuildTasksRunner.Validate(taskList, buildContext); if (exitCode >= ReturnCode.Success) #if SBP_PROFILER_ENABLE { exitCode = BuildTasksRunner.RunProfiled(taskList, buildContext); } #else { exitCode = BuildTasksRunner.Run(taskList, buildContext); } #endif if (Directory.Exists(parameters.TempOutputFolder)) { Directory.Delete(parameters.TempOutputFolder, true); } if (buildLog != null) { string buildLogPath = parameters.GetOutputFilePathForIdentifier("buildlogtep.json"); Directory.CreateDirectory(Path.GetDirectoryName(buildLogPath)); File.WriteAllText(parameters.GetOutputFilePathForIdentifier("buildlogtep.json"), buildLog.FormatForTraceEventProfiler()); } } long maximumCacheSize = ScriptableBuildPipeline.maximumCacheSize * BuildCache.k_BytesToGigaBytes; BuildCache.PruneCache_Background(maximumCacheSize); return(exitCode); }
public static ReturnCode BuildAssetBundles(string outputPath, CompressionType compressionMode, BuildTarget buildTarget, BuildTargetGroup buildGroup, out IBundleBuildResults results) { BundleBuildContent buildContent = new BundleBuildContent(ContentBuildInterface.GenerateAssetBundleBuilds()); BundleBuildParameters buildParams = new BundleBuildParameters(buildTarget, buildGroup, outputPath); SetupBuildCacheServer(buildParams); switch (compressionMode) { case CompressionType.None: buildParams.BundleCompression = BuildCompression.Uncompressed; break; case CompressionType.Lz4: buildParams.BundleCompression = BuildCompression.LZ4; break; default: buildParams.BundleCompression = BuildCompression.LZMA; break; } return(ContentPipeline.BuildAssetBundles(buildParams, buildContent, out results)); }
public override void PostProcessBundles(AddressableAssetGroup assetGroup, List <string> buildBundles, List <string> outputBundles, IBundleBuildResults buildResult, ResourceManagerRuntimeData runtimeData, List <ContentCatalogDataEntry> locations, FileRegistry registry, Dictionary <string, ContentCatalogDataEntry> primaryKeyToCatalogEntry, Dictionary <string, string> bundleRenameMap, List <Action> postCatalogUpdateCallbacks) { var schema = assetGroup.GetSchema <BundledAssetGroupSchema>(); if (schema == null) { return; } var path = schema.BuildPath.GetValue(assetGroup.Settings); if (string.IsNullOrEmpty(path)) { return; } for (int i = 0; i < buildBundles.Count; ++i) { if (primaryKeyToCatalogEntry.TryGetValue(buildBundles[i], out ContentCatalogDataEntry dataEntry)) { var info = buildResult.BundleInfos[buildBundles[i]]; var requestOptions = new AssetBundleEncryptRequestOptions { Crc = schema.UseAssetBundleCrc ? info.Crc : 0, UseCrcForCachedBundle = schema.UseAssetBundleCrcForCachedBundles, Hash = schema.UseAssetBundleCache ? info.Hash.ToString() : "", ChunkedTransfer = schema.ChunkedTransfer, RedirectLimit = schema.RedirectLimit, RetryCount = schema.RetryCount, Timeout = schema.Timeout, BundleName = Path.GetFileName(info.FileName), BundleSize = GetFileSize(info.FileName) }; dataEntry.Data = requestOptions; int extensionLength = Path.GetExtension(outputBundles[i]).Length; string[] deconstructedBundleName = outputBundles[i].Substring(0, outputBundles[i].Length - extensionLength).Split('_'); string reconstructedBundleName = string.Join("_", deconstructedBundleName, 1, deconstructedBundleName.Length - 1) + ".bundle"; outputBundles[i] = ConstructAssetBundleName(assetGroup, schema, info, reconstructedBundleName); dataEntry.InternalId = dataEntry.InternalId.Remove(dataEntry.InternalId.Length - buildBundles[i].Length) + outputBundles[i]; dataEntry.Keys[0] = outputBundles[i]; ReplaceDependencyKeys(buildBundles[i], outputBundles[i], locations); Debug.Log(outputBundles[i] + "crc = " + requestOptions.Crc + " hash = " + requestOptions.Hash); if (!m_BundleToInternalId.ContainsKey(buildBundles[i])) { m_BundleToInternalId.Add(buildBundles[i], dataEntry.InternalId); } if (dataEntry.InternalId.StartsWith("http:\\")) { dataEntry.InternalId = dataEntry.InternalId.Replace("http:\\", "http://").Replace("\\", "/"); } if (dataEntry.InternalId.StartsWith("https:\\")) { dataEntry.InternalId = dataEntry.InternalId.Replace("https:\\", "https://").Replace("\\", "/"); } dataEntry.InternalId = CheckNameNeedStripped(assetGroup, dataEntry.InternalId); } else { Debug.LogWarningFormat("Unable to find ContentCatalogDataEntry for bundle {0}.", outputBundles[i]); } //获取bundle的保存路径 var targetPath = Path.Combine(path, outputBundles[i]); //判断目录是否存在 if (!Directory.Exists(Path.GetDirectoryName(targetPath))) { Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); } File.Copy(Path.Combine(assetGroup.Settings.buildSettings.bundleBuildPath, buildBundles[i]), targetPath, true); var nameWithourHash = CheckNameNeedStripped(assetGroup, outputBundles[i]); EncodeAssetBundleBySetOffset(nameWithourHash, targetPath); var bundleName = Path.GetFileName(nameWithourHash); if (IsBuildInAssetBundle(bundleName)) { string RuntimePath = UnityEngine.AddressableAssets.Addressables.RuntimePath; string destPath = Path.Combine(System.Environment.CurrentDirectory, RuntimePath, PlatformMappingService.GetPlatform().ToString(), nameWithourHash); if (!Directory.Exists(Path.GetDirectoryName(destPath))) { Directory.CreateDirectory(Path.GetDirectoryName(destPath)); } if (!File.Exists(destPath)) { File.Copy(targetPath, destPath); } } AddPostCatalogUpdatesInternal(assetGroup, postCatalogUpdateCallbacks, dataEntry, targetPath); registry.AddFile(targetPath); } }