// 根据 targets 遍历产生所有实际资源列表 assets public static bool ScanBundle(BundleBuilderData data, BundleBuilderData.BundleInfo bundle) { if (!bundle.enabled) { return(false); } foreach (var targetAsset in bundle.targets) { if (targetAsset.enabled /*&& targetAsset.IsBuildPlatform(buildPlatform)*/) { Scan(data, bundle, targetAsset.target, targetAsset.platform); } } if (bundle.Slice(data)) { data.MarkAsDirty(); } return(true); }
public static AssetBundleBuild[] GenerateAssetBundleBuilds(BundleBuilderData data) { var builds = new List <AssetBundleBuild>(); foreach (var bundle in data.bundles) { if (bundle.type != Manifest.BundleType.AssetBundle) { continue; } for (var splitIndex = 0; splitIndex < bundle.splits.Count; splitIndex++) { var bundleSplit = bundle.splits[splitIndex]; var assetNames = new List <string>(); for (var assetIndex = 0; assetIndex < bundleSplit.assets.Count; assetIndex++) { var asset = bundleSplit.assets[assetIndex]; var assetPath = AssetDatabase.GetAssetPath(asset); assetNames.Add(assetPath); } if (assetNames.Count != 0) { var names = assetNames.ToArray(); var build = new AssetBundleBuild(); build.assetBundleName = bundleSplit.name; build.assetNames = names; build.addressableNames = names; builds.Add(build); // Debug.Log($"{build.assetBundleName}: {build.assetNames.Length}"); } else { Debug.LogWarning($"empty build split {bundle.name}_{splitIndex}"); } } } return(builds.ToArray()); }
// 生成打包 public static void Build(BundleBuilderData data, string outputPath, BuildTarget targetPlatform) { BundleBuilder.Scan(data, targetPlatform); var assetBundleBuilds = GenerateAssetBundleBuilds(data); var zipArchiveBuilds = GenerateZipArchiveBuilds(data); // var sceneBundleBuilds = GenerateSceneBundleBuilds(data); if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } AssetBundleManifest assetBundleManifest = null; ZipArchiveManifest zipArchiveManifest = null; // UnityEditor.Build.Reporting.BuildReport report = null; // if (sceneBundleBuilds.Length != 0) // { // Debug.Log($"build {sceneBundleBuilds.Length} scene bundles"); // var levels = new List<string>(sceneBundleBuilds.Length); // foreach (var build in sceneBundleBuilds) // { // levels.Add(build.scenePath); // } // report = BuildPipeline.BuildPlayer(levels.ToArray(), outputPath, targetPlatform, BuildOptions.BuildAdditionalStreamedScenes); // } if (assetBundleBuilds.Length != 0) { assetBundleManifest = BuildPipeline.BuildAssetBundles(outputPath, assetBundleBuilds, BuildAssetBundleOptions.None, targetPlatform); } if (zipArchiveBuilds.Length != 0) { zipArchiveManifest = BuildZipArchives(outputPath, zipArchiveBuilds, targetPlatform); } BuildManifest(data, outputPath, assetBundleManifest, zipArchiveManifest); Cleanup(outputPath, assetBundleManifest, zipArchiveManifest); Debug.Log($"build bundles finished {DateTime.Now}. {assetBundleBuilds.Length} assetbundles. {zipArchiveBuilds.Length} zip archives."); }
private static bool CollectAssetList(BundleBuilderData data, BundleBuilderData.BundleInfo bundle, AssetListData asset, PackagePlatform platform) { for (var index = 0; index < asset.timestamps.Count; index++) { var ts = asset.timestamps[index]; var assetPath = AssetDatabase.GUIDToAssetPath(ts.guid); // 剔除 filelist 对象 if (!Directory.Exists(assetPath)) { //TODO: 场景需要单独拆包 if (assetPath.EndsWith(".unity")) { continue; } var mainAsset = AssetDatabase.LoadMainAssetAtPath(assetPath); CollectAsset(data, bundle, mainAsset, assetPath, platform); } } return(true); }
public static void Scan(BundleBuilderData data, BundleBuilderData.BundleInfo bundle, BundleBuilderData.BundleAssetTarget target, Object asset) { if (asset == null) { return; } var targetPath = AssetDatabase.GetAssetPath(asset); if (Directory.Exists(targetPath)) { // 是一个目录 foreach (var directory in Directory.GetDirectories(targetPath)) { Scan(data, bundle, target, AssetDatabase.LoadMainAssetAtPath(directory)); } foreach (var file in Directory.GetFiles(targetPath)) { if (file.EndsWith(".meta")) { continue; } var fileAsset = AssetDatabase.LoadMainAssetAtPath(file); Scan(data, bundle, target, fileAsset); } } else { if (CollectAsset(data, bundle, asset)) { if (bundle.AddAssetOrder(asset)) { data.MarkAsDirty(); } } } }
public static bool ContainsAsset(BundleBuilderData data, Object assetObject) { foreach (var bundle in data.bundles) { foreach (var split in bundle.splits) { if (split.assets.Contains(assetObject)) { return(true); } foreach (var slice in split.slices) { foreach (var asset in slice.assets) { if (asset == assetObject) { return(true); } } } } } return(false); }
public static void Scan(BundleBuilderData data, BundleBuilderData.BundleInfo bundle, AssetFilter filter, Object asset) { if (asset == null) { return; } var targetPath = AssetDatabase.GetAssetPath(asset); if (Directory.Exists(targetPath)) { // 是一个目录 foreach (var directory in Directory.GetDirectories(targetPath)) { Scan(data, bundle, filter, AssetDatabase.LoadMainAssetAtPath(directory)); } foreach (var file in Directory.GetFiles(targetPath)) { if (file.EndsWith(".meta")) { continue; } if (filter.extensions != null) { var skip = false; for (int i = 0, size = filter.extensions.Length; i < size; i++) { var ext = filter.extensions[i]; if (!string.IsNullOrEmpty(ext) && file.EndsWith(ext)) { skip = true; break; } } if (skip) { continue; } } var fileAsset = AssetDatabase.LoadMainAssetAtPath(file); if (filter.types != 0) { if ((filter.types & BundleAssetTypes.Prefab) == 0 && fileAsset is GameObject && file.EndsWith(".prefab")) { continue; } else if ((filter.types & BundleAssetTypes.TextAsset) == 0 && fileAsset is TextAsset) { continue; } else if ((filter.types & BundleAssetTypes.Animation) == 0 && (fileAsset is Animation || fileAsset is AnimationClip)) { continue; } else if ((filter.types & BundleAssetTypes.Material) == 0 && fileAsset is Material) { continue; } else if ((filter.types & BundleAssetTypes.Texture) == 0 && fileAsset is Texture) { continue; } else if ((filter.types & BundleAssetTypes.Audio) == 0 && fileAsset is AudioClip) { continue; } } Scan(data, bundle, filter, fileAsset); } } else { if (!ContainsAsset(data, asset)) { var index = 0; BundleBuilderData.BundleSplit split = null; if (bundle.splits.Count > 0) { index = bundle.splits.Count - 1; split = bundle.splits[index]; } if (split == null || filter.size >= 1 && split.assets.Count >= filter.size) { split = new BundleBuilderData.BundleSplit(); index = bundle.splits.Count; if (filter.size == 0) { split.name = bundle.name; } else { var dot = bundle.name.LastIndexOf('.'); if (dot >= 0) { split.name = bundle.name.Substring(0, dot) + "_" + index + bundle.name.Substring(dot); } else { split.name = bundle.name + "_" + index; } } bundle.splits.Add(split); } split.assets.Add(asset); } } }
// 生成清单 public static void BuildManifest(BundleBuilderData data, string outputPath, AssetBundleManifest assetBundleManifest, ZipArchiveManifest zipArchiveManifest) { var manifest = new Manifest(); if (assetBundleManifest != null) { var assetBundles = assetBundleManifest.GetAllAssetBundles(); foreach (var assetBundle in assetBundles) { BundleBuilderData.BundleInfo bundleInfo; BundleBuilderData.BundleSplit bundleSplit; if (TryGetBundleSplit(data, assetBundle, out bundleInfo, out bundleSplit)) { // Debug.Log(bundleInfo.name); var assetBundlePath = Path.Combine(outputPath, assetBundle); using (var stream = File.OpenRead(assetBundlePath)) { var fileInfo = new FileInfo(assetBundlePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.AssetBundle; bundle.name = bundleSplit.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.startup = bundleInfo.load == BundleLoad.Startup; bundle.priority = bundleInfo.priority; foreach (var asset in bundleSplit.assets) { var assetPath = AssetDatabase.GetAssetPath(asset); bundle.assets.Add(assetPath); } bundle.dependencies = assetBundleManifest.GetAllDependencies(assetBundle); manifest.bundles.Add(bundle); } } } } if (zipArchiveManifest != null) { foreach (var zipArchive in zipArchiveManifest.archives) { var bundleInfo = GetBundleInfo(data, zipArchive.name); var zipArchivePath = Path.Combine(outputPath, zipArchive.name); using (var stream = File.OpenRead(zipArchivePath)) { var fileInfo = new FileInfo(zipArchivePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.ZipArchive; bundle.name = zipArchive.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.startup = bundleInfo.load == BundleLoad.Startup; bundle.priority = bundleInfo.priority; foreach (var assetPath in zipArchive.assets) { // var assetPath = AssetDatabase.GetAssetPath(asset.target); bundle.assets.Add(assetPath); } // bundle.dependencies = null; manifest.bundles.Add(bundle); } } } if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } var json = JsonUtility.ToJson(manifest); var jsonChecksum = Utils.Crc16.ToString(Utils.Crc16.ComputeChecksum(System.Text.Encoding.UTF8.GetBytes(json))); var manifestPath = Path.Combine(outputPath, "manifest.json"); var manifestChecksumPath = Path.Combine(outputPath, "checksum.txt"); File.WriteAllText(manifestPath, json); File.WriteAllText(manifestChecksumPath, jsonChecksum); }
public void SetData(BundleBuilderData data) { _data = data; Reload(); }
// 生成清单 public static void BuildManifest(BundleBuilderData data, string outputPath, AssetBundleManifest assetBundleManifest, ZipArchiveManifest zipArchiveManifest, out EmbeddedManifest embeddedManifest) { var manifest = new Manifest(); embeddedManifest = new EmbeddedManifest(); if (assetBundleManifest != null) { var assetBundles = assetBundleManifest.GetAllAssetBundles(); foreach (var assetBundle in assetBundles) { BundleBuilderData.BundleInfo bundleInfo; BundleBuilderData.BundleSplit bundleSplit; if (TryGetBundleSplit(data, assetBundle, out bundleInfo, out bundleSplit)) { // Debug.Log(bundleInfo.name); var assetBundlePath = Path.Combine(outputPath, assetBundle); using (var stream = File.OpenRead(assetBundlePath)) { var fileInfo = new FileInfo(assetBundlePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.AssetBundle; bundle.name = bundleSplit.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.load = bundleInfo.load; bundle.priority = bundleInfo.priority; foreach (var asset in bundleSplit.assets) { var assetPath = AssetDatabase.GetAssetPath(asset); bundle.assets.Add(assetPath); } bundle.dependencies = assetBundleManifest.GetAllDependencies(assetBundle); manifest.bundles.Add(bundle); if (bundleInfo.streamingAssets) { embeddedManifest.bundles.Add(new EmbeddedManifest.BundleInfo() { name = bundle.name, checksum = bundle.checksum, size = bundle.size, }); } } } } } if (zipArchiveManifest != null) { foreach (var zipArchive in zipArchiveManifest.archives) { var bundleInfo = GetBundleInfo(data, zipArchive.name); var zipArchivePath = Path.Combine(outputPath, zipArchive.name); using (var stream = File.OpenRead(zipArchivePath)) { var fileInfo = new FileInfo(zipArchivePath); var checksum = new Utils.Crc16(); checksum.Update(stream); var bundle = new Manifest.BundleInfo(); bundle.type = Manifest.BundleType.ZipArchive; bundle.name = zipArchive.name; bundle.checksum = checksum.hex; bundle.size = (int)fileInfo.Length; bundle.load = bundleInfo.load; bundle.priority = bundleInfo.priority; foreach (var assetPath in zipArchive.assets) { // var assetPath = AssetDatabase.GetAssetPath(asset.target); bundle.assets.Add(assetPath); } // bundle.dependencies = null; manifest.bundles.Add(bundle); if (bundleInfo.streamingAssets) { embeddedManifest.bundles.Add(new EmbeddedManifest.BundleInfo() { name = bundle.name, checksum = bundle.checksum, size = bundle.size, }); } } } } if (!Directory.Exists(outputPath)) { Directory.CreateDirectory(outputPath); } OutputManifest(manifest, outputPath); OutputEmbeddedManifest(embeddedManifest, outputPath); }
public static void Scan(BundleBuilderData data, BundleBuilderData.BundleInfo bundle, BundleBuilderData.BundleAssetTarget target) { Scan(data, bundle, target, target.target); }
public static AssetAttributes DrawSingleAssetAttributes(BundleBuilderData data, string assetGuid, Action <FileInfo> additionalOp = null) { return(DrawSingleAssetAttributes(data, assetGuid, null, false, additionalOp)); }
private static AssetAttributes DrawSearchResultAssetAttributes(Rect elementRect, BundleBuilderData data, SearchResult result, BundleBuilderWindow builder, bool batchMode) { var assetPath = result.assetPath; var fileInfoWidth = 60f; var sliceInfoWidth = 260f; var fileInfo = new FileInfo(assetPath); var fileSize = fileInfo.Exists ? fileInfo.Length : 0L; var attrs = data.GetAssetPathAttributes(assetPath); var bNew = attrs == null; if (bNew) { attrs = new AssetAttributes(); } var iRect = new Rect(elementRect.x, elementRect.y, 110f, elementRect.height); var nAssetPacker = (AssetPacker)EditorGUI.EnumPopup(iRect, attrs.packer); iRect.x += 110f + 8f; iRect.width = 220f; iRect.height = elementRect.height - 2f; var nPriority = EditorGUI.IntSlider(iRect, attrs.priority, 0, data.priorityMax); iRect.x += iRect.width; iRect.width = 180f; iRect.height = elementRect.height - 4f; if (assetPath.StartsWith("Assets/")) { var assetObject = AssetDatabase.LoadMainAssetAtPath(assetPath); EditorGUI.ObjectField(iRect, assetObject, typeof(Object), false); } else { EditorGUI.LabelField(iRect, "<External>"); } iRect.x += iRect.width; iRect.width = fileInfoWidth; iRect.height = elementRect.height - 2f; EditorGUI.LabelField(iRect, PathUtils.GetFileSizeString(fileSize), _rightAlignStyle); iRect.x += iRect.width; iRect.width = elementRect.width - iRect.x - sliceInfoWidth - 20f + 20f; EditorGUI.TextField(iRect, assetPath); iRect.x += iRect.width; iRect.width = sliceInfoWidth; iRect.height = elementRect.height - 2f; if (result.bundleInfo != null) { EditorGUI.TextField(iRect, result.bundleSlice.name); iRect.x += iRect.width; iRect.width = 20f; if (GUI.Button(iRect, ">")) { BundleAssetsWindow.Inspect(data, new List <BundleBuilderData.BundleInfo>(new[] { result.bundleInfo })); } } else { EditorGUI.BeginDisabledGroup(true); EditorGUI.TextField(iRect, "<null>"); iRect.x += iRect.width; iRect.width = 20f; GUI.Button(iRect, ">"); EditorGUI.EndDisabledGroup(); } if (batchMode) { if (nAssetPacker != attrs.packer) { builder?.ApplyAllMarks(attributes => attributes.packer = nAssetPacker); } if (nPriority != attrs.priority) { var deltaPriority = nPriority - attrs.priority; builder?.ApplyAllMarks(attributes => attributes.priority = Math.Max(0, Math.Min(data.priorityMax, attributes.priority + deltaPriority))); } } else { if (nAssetPacker != attrs.packer) { attrs.packer = nAssetPacker; data.MarkAsDirty(); } if (nPriority != attrs.priority) { attrs.priority = nPriority; data.MarkAsDirty(); } if (attrs.priority == 0 && attrs.packer == AssetPacker.Auto) { data.RemoveAssetPathAttributes(assetPath); } else if (bNew) { if (attrs.priority != 0 || attrs.packer != AssetPacker.Auto) { var newAttributes = data.AddAssetPathAttributes(assetPath); newAttributes.priority = attrs.priority; newAttributes.packer = attrs.packer; } } } return(attrs); }
public void SetBundles(BundleBuilderData data, IList <BundleBuilderData.BundleInfo> bundles) { _data = data; _bundles = bundles; }
private static AssetAttributes DrawSingleAssetAttributes(BundleBuilderData data, string assetGuid, BundleBuilderWindow builder, bool batchMode, bool rLookup) { var assetPath = AssetDatabase.GUIDToAssetPath(assetGuid); var assetObject = AssetDatabase.LoadMainAssetAtPath(assetPath); var attrs = data.GetAssetAttributes(assetGuid); var bNew = attrs == null; if (bNew) { attrs = new AssetAttributes(); } var nAssetPacker = (AssetPacker)EditorGUILayout.EnumPopup(attrs.packer, GUILayout.MaxWidth(80f)); var nPriority = EditorGUILayout.IntSlider(attrs.priority, 0, data.priorityMax, GUILayout.MaxWidth(220f)); EditorGUILayout.ObjectField(assetObject, typeof(Object), false, GUILayout.MaxWidth(180f)); EditorGUILayout.TextField(assetPath); if (rLookup) { BundleBuilderData.BundleInfo rBundleInfo; BundleBuilderData.BundleSplit rBundleSplit; BundleBuilderData.BundleSlice rBundleSlice; var exists = data.Lookup(assetGuid, out rBundleInfo, out rBundleSplit, out rBundleSlice); EditorGUI.BeginDisabledGroup(true); EditorGUILayout.TextField(exists ? rBundleSlice.name : "<null>"); EditorGUI.EndDisabledGroup(); if (GUILayout.Button(">", GUILayout.Width(20f))) { BundleAssetsWindow.Inspect(data, new List <BundleBuilderData.BundleInfo>(new[] { rBundleInfo })); } } if (batchMode) { if (nAssetPacker != attrs.packer) { builder?.ApplyAllMarks(attributes => attributes.packer = nAssetPacker); } if (nPriority != attrs.priority) { var deltaPriority = nPriority - attrs.priority; builder?.ApplyAllMarks(attributes => attributes.priority = Math.Max(0, Math.Min(data.priorityMax, attributes.priority + deltaPriority))); } } else { if (nAssetPacker != attrs.packer) { attrs.packer = nAssetPacker; data.MarkAsDirty(); } if (nPriority != attrs.priority) { attrs.priority = nPriority; data.MarkAsDirty(); } if (attrs.priority == 0 && attrs.packer == AssetPacker.Auto) { data.RemoveAssetAttributes(assetGuid); } else if (bNew) { if (attrs.priority != 0 || attrs.packer != AssetPacker.Auto) { var newAttributes = data.AddAssetAttributes(assetGuid); newAttributes.priority = attrs.priority; newAttributes.packer = attrs.packer; } } } return(attrs); }
public static AssetAttributes DrawSingleAssetAttributes(BundleBuilderData data, string assetGuid) { return(DrawSingleAssetAttributes(data, assetGuid, null, false, null)); }
private static AssetAttributes DrawSingleAssetAttributes(BundleBuilderData data, string assetGuid, BundleBuilderWindow builder, bool batchMode, Action additionalOp) { var assetPath = AssetDatabase.GUIDToAssetPath(assetGuid); var assetObject = AssetDatabase.LoadMainAssetAtPath(assetPath); var attrs = data.GetAssetAttributes(assetGuid); var bNew = attrs == null; if (bNew) { attrs = new AssetAttributes(); } var nAssetPacker = (AssetPacker)EditorGUILayout.EnumPopup(attrs.packer, GUILayout.MaxWidth(110f)); var nPriority = EditorGUILayout.IntSlider(attrs.priority, 0, data.priorityMax, GUILayout.MaxWidth(220f)); EditorGUILayout.ObjectField(assetObject, typeof(Object), false, GUILayout.MaxWidth(180f)); EditorGUILayout.TextField(assetPath); var fileInfoWidth = 60f; EditorGUILayout.LabelField(GetFileSizeString(assetPath), _rightAlignStyle, GUILayout.MaxWidth(fileInfoWidth)); additionalOp?.Invoke(); if (batchMode) { if (nAssetPacker != attrs.packer) { builder?.ApplyAllMarks(attributes => attributes.packer = nAssetPacker); } if (nPriority != attrs.priority) { var deltaPriority = nPriority - attrs.priority; builder?.ApplyAllMarks(attributes => attributes.priority = Math.Max(0, Math.Min(data.priorityMax, attributes.priority + deltaPriority))); } } else { if (nAssetPacker != attrs.packer) { attrs.packer = nAssetPacker; data.MarkAsDirty(); } if (nPriority != attrs.priority) { attrs.priority = nPriority; data.MarkAsDirty(); } if (attrs.priority == 0 && attrs.packer == AssetPacker.Auto) { data.RemoveAssetAttributes(assetGuid); } else if (bNew) { if (attrs.priority != 0 || attrs.packer != AssetPacker.Auto) { var newAttributes = data.AddAssetAttributes(assetGuid); newAttributes.priority = attrs.priority; newAttributes.packer = attrs.packer; } } } return(attrs); }
// 最终资源 private static bool CollectAsset(BundleBuilderData data, BundleBuilderData.BundleInfo bundle, Object asset, string assetPath, PackagePlatform platform) { if (asset == null) { return(false); } var listData = asset as AssetListData; if (listData != null) { return(CollectAssetList(data, bundle, listData, platform)); } for (var splitIndex = 0; splitIndex < bundle.splits.Count; splitIndex++) { var split = bundle.splits[splitIndex]; var ruleMatch = false; if (split.rules.Count > 0) { for (var ruleIndex = 0; ruleIndex < split.rules.Count; ruleIndex++) { var rule = split.rules[ruleIndex]; if (rule.exclude) { if (IsRuleMatched(rule, asset, assetPath)) { break; } } else { if (IsRuleMatched(rule, asset, assetPath)) { ruleMatch = true; break; } } } } else { ruleMatch = true; } if (ruleMatch) { if (!ContainsAsset(data, asset) && split.AddObject(asset, platform)) { if (data.extractShaderVariantCollections) { CheckShaderVariants(data, bundle, asset, assetPath, platform); } } return(true); } } return(false); }