Unity AssetBundle设置名称优化
发表于2018-04-03
在大部分的 Unity 分析打包 AssetBundle 过程中,是采用对资源设置 AssetBundle 名称标签的方式来进行打包,类似如下:
public static void SetBundleName(string assetPath, string bundleName) { var importer = AssetImporter.GetAtPath(assetPath); if (importer && importer.assetBundleName != bundleName) { importer.assetBundleName = bundleName; } } private static void BuildAssetBundlesInter(string outputPath, AssetBundleBuildOptions options) { AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(outputPath, BuildAssetBundleOptions.UncompressedAssetBundle, GetBuildTarget()); }
每设置一个资源的 AssetBundle 名称,都会导致 Unity 写入其 .meta 文件,这样在分析的过程耗费不少时间。而且在打包完毕,又得重新设置所有资源的 AssetBundle 名称为空,否则仓库会提示有文件变化。基于此,本篇文章就和大家介绍下对AssetBundle的名称优化。
思路
修改流程,改成传入 AssetBundleBuild[] 的方式进行打包,这样就无需设置资源的 AssetBundle 名称。但是不能简单的把结果保存为 AssetBundleBuild[] 数组对象,因为打包工具支持当次不再分析资源,直接使用上一次的分析结果。所以要把 AssetBundleBuild[] 结果存为临时文件,方便下次使用,正常来说,这个临时文件一般只对当天的资源有效即可,当更新了资源,肯定得重新分析资源,不能再使用上次的结果。所以,只需要把这临时文件放在 Temp 目录下即可。
解决
创建一个独立类,来管理分析的 AssetBundle 构建信息:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using UnityEditor; /// <summary> /// AssetBundle 分析映射 /// </summary> public static class AssetBundleBuildMap { private static AssetBundleMap assetBundleMap; public static void Clear() { if (assetBundleMap != null) { assetBundleMap = null; } } /// <summary> /// 普通资源设置 AssetBundle 名称接口 /// </summary> /// <param name="assetPath"></param> /// <param name="assetBundleName"></param> public static void SetAssetPathAssetBundleName(string assetPath, string assetBundleName) { if (assetBundleMap == null) { assetBundleMap = new AssetBundleMap(); } assetBundleMap.AddMap(assetPath, assetBundleName); } public static bool IsAssetPathHasAssetBundleName(string assetPath) { if (assetBundleMap == null) { return false; } return assetBundleMap.assetPathSet.Contains(assetPath); } public static List<string> GetAllAssetBundleNames() { if (assetBundleMap == null) { return null; } List<string> allAssetBundleNames = assetBundleMap.assetBundleDict.Keys.ToList(); allAssetBundleNames.Sort(EditorUtility.NaturalCompare); return allAssetBundleNames; } public static List<string> GetAssetPathsFromAssetBundle(string assetBundleName) { if (assetBundleMap == null) { return null; } List<string> assetPaths; if (assetBundleMap.assetBundleDict.TryGetValue(assetBundleName, out assetPaths)) { assetPaths.Sort(EditorUtility.NaturalCompare); return assetPaths; } return null; } /// <summary> /// 最终需要进行打包的资产构建列表 /// </summary> /// <returns></returns> public static AssetBundleBuild[] GetAssetBundleBuilds() { List<AssetBundleBuild> assetBundleBuilds = new List<AssetBundleBuild>(); string tempPath = "Temp/AssetBundleBuildAnalyze"; if (assetBundleMap == null) { assetBundleMap = AssetBundleMap.MakeByLoad(tempPath); } else { assetBundleMap.Save(tempPath); } assetBundleBuilds.AddRange(assetBundleMap.GetBuilds()); return assetBundleBuilds.ToArray(); } private class AssetBundleMap { public readonly HashSet<string> assetPathSet = new HashSet<string>(); public Dictionary<string, List<string>> assetBundleDict = new Dictionary<string, List<string>>(); public void AddMap(string assetPath, string assetBundleName) { if (string.IsNullOrEmpty(assetPath) || string.IsNullOrEmpty(assetBundleName)) { return; } if (assetPathSet.Contains(assetPath)) { return; } assetPathSet.Add(assetPath); List<string> assetPaths; if (assetBundleDict.TryGetValue(assetBundleName, out assetPaths)) { assetPaths.Add(assetPath); } else { assetPaths = new List<string> { assetPath }; assetBundleDict.Add(assetBundleName, assetPaths); } } public List<AssetBundleBuild> GetBuilds() { List<AssetBundleBuild> assetBundleBuilds = new List<AssetBundleBuild>(); foreach (var kv in assetBundleDict) { assetBundleBuilds.Add(new AssetBundleBuild() { assetBundleName = kv.Key, assetNames = kv.Value.ToArray() }); } return assetBundleBuilds; } public void Save(string tempPath) { using (MemoryStream stream = new MemoryStream()) { new BinaryFormatter().Serialize(stream, assetBundleDict); File.WriteAllBytes(tempPath, stream.ToArray()); } } public static AssetBundleMap MakeByLoad(string tempPath) { AssetBundleMap map = new AssetBundleMap(); if (File.Exists(tempPath)) { byte[] bytes = File.ReadAllBytes(tempPath); using (MemoryStream stream = new MemoryStream(bytes)) { map.assetBundleDict = new BinaryFormatter().Deserialize(stream) as Dictionary<string, List<string>>; } } return map; } } }
最终调用的方式如下:
private static void BuildAssetBundlesInter(string outputPath, AssetBundleBuildOptions options) { AssetBundleBuild[] assetBundleBuilds = AssetBundleBuildMap.GetAssetBundleBuilds(); AssetBundleManifest manifest = BuildPipeline.BuildAssetBundles(outputPath, assetBundleBuilds, BuildAssetBundleOptions.UncompressedAssetBundle, GetBuildTarget()); AssetBundleBuildMap.Clear(); }
来自:https://blog.csdn.net/akof1314/article/details/77751512