/// <summary> /// 删除未使用的AB,可能是上次打包出来的,而这一次没生成的 /// </summary> private void RemoveUnused() { var all = context.allTarget; HashSet <string> usedSet = new HashSet <string>(); for (int i = 0; i < all.Count; i++) { ABTarget target = all[i]; if (target.needSelfExport) { usedSet.Add(target.bundleName); } } DirectoryInfo di = new DirectoryInfo(ABExportConst.PlatformBundleSavePath);; FileInfo[] abFiles = di.GetFiles("*.ab"); for (int i = 0; i < abFiles.Length; i++) { FileInfo fi = abFiles[i]; if (usedSet.Add(fi.Name)) { Debug.Log("Remove unused AB : " + fi.Name); fi.Delete(); File.Delete(fi.FullName + ".manifest"); } } }
public override void Save(Stream stream, ABTarget[] targets) { StreamWriter sw = new StreamWriter(stream); //写入文件头判断文件类型用,ABDT 意思即 Asset-Bundle-Data-Text sw.WriteLine("ABDT"); for (int i = 0; i < targets.Length; i++) { ABTarget target = targets[i]; HashSet <ABTarget> deps = target.GetAllDependencies(); sw.WriteLine(target.assetPath); // debug name sw.WriteLine(target.bundleName); // bundle name sw.WriteLine(target.fileHash); // file hash sw.WriteLine((int)target.compositeType); // export type sw.WriteLine(deps.Count); foreach (ABTarget item in deps) { sw.WriteLine(item.bundleName); } sw.WriteLine("<------------->"); } sw.Close(); }
/// <summary> /// 添加本对象的依赖 /// </summary> /// <param name="target"></param> private void AddDepend(ABTarget target) { if (target == this || this.ContainsDepend(target)) { return; } if (target.ContainsDepend(this)) { Debug.LogError("出现循环依赖:" + target.bundleName + " 与 " + bundleName); return; } dependencies.Add(target); target.reverseDependencies.Add(this); //遍历依赖树依赖我的对象不需要再依赖该目标 IEnumerable <ABTarget> cols = dependencies; cols = new ABTarget[] { target }; foreach (var at in cols) { var e = reverseDependencies.GetEnumerator(); while (e.MoveNext()) { ABTarget dc = e.Current; if (dc == null) { continue; } dc.RemoveDepend(at); } e.Dispose(); } }
/// <summary> /// 添加根目标 /// </summary> /// <param name="fliter"></param> private void AddRootTarget(ABFliter fliter) { var files = fliter.GetFiles(); files.ForEach((file) => { var target = ABTarget.GetOrCreateTarget(context, file); if (target == null) { Debug.LogError(file); return; } target.exportType = ABExportType.Root; }); }
private void GetDependecies(HashSet <ABTarget> targets) { var ie = dependencies.GetEnumerator(); while (ie.MoveNext()) { ABTarget target = ie.Current; if (target.needSelfExport) { targets.Add(target); } else { target.GetDependecies(targets); } } }
/// <summary> /// 是否已经依赖(遍历依赖树) /// </summary> /// <param name="target"></param> /// <returns></returns> private bool ContainsDepend(ABTarget target) { if (dependencies.Contains(target)) { return(true); } var e = dependencies.GetEnumerator(); while (e.MoveNext()) { if (e.Current.ContainsDepend(target)) { return(true); } } return(false); }
/// <summary> /// 从上下文中获取或创建Target /// </summary> /// <param name="context"></param> /// <param name="file"></param> /// <param name="t"></param> /// <returns></returns> public static ABTarget GetOrCreateTarget(ABExportContext context, FileInfo file, System.Type t = null) { ABTarget target = null; string fullPath = file.FullName; int index = fullPath.IndexOf("Assets"); if (index < 0) { return(null); } //通过assetPath寻找 string assetPath = fullPath.Substring(index); if (context.TryGetTarget(assetPath, out target)) { return(target); } UnityEngine.Object obj = t != null?AssetDatabase.LoadAssetAtPath(assetPath, t) : AssetDatabase.LoadMainAssetAtPath(assetPath); if (obj == null) { return(null); } //通过InstanceId寻找 int instID = obj.GetInstanceID(); if (context.TryGetTarget(instID, out target)) { return(target); } //创建新的Target target = new ABTarget(obj, file, assetPath); target.context = context; context.AddTarget(target); return(target); }
public override void Save(Stream stream, ABTarget[] targets) { BinaryWriter sw = new BinaryWriter(stream); //写入文件头判断文件类型用,ABDB 意思即 Asset-Bundle-Data-Binary sw.Write(new char[] { 'A', 'B', 'D', 'B' }); List <string> bundleNames = new List <string>(); for (int i = 0; i < targets.Length; i++) { ABTarget target = targets[i]; bundleNames.Add(target.bundleName); } //写入文件名池 sw.Write(bundleNames.Count); for (int i = 0; i < bundleNames.Count; i++) { sw.Write(bundleNames[i]); } //写入详细信息 for (int i = 0; i < targets.Length; i++) { ABTarget target = targets[i]; HashSet <ABTarget> deps = target.GetAllDependencies(); sw.Write(target.assetPath); //debug name sw.Write(bundleNames.IndexOf(target.bundleName)); //bundle name sw.Write(target.fileHash); //file hash sw.Write((int)target.compositeType); //export type sw.Write(deps.Count); foreach (ABTarget item in deps) { sw.Write(bundleNames.IndexOf(item.bundleName)); } } sw.Close(); }
/// <summary> /// 进行最后的导出操作 /// </summary> /// <param name="exportDir"></param> private void Export(string exportDir) { var allTarget = context.allTarget; //标记所有 asset bundle name,如果需要单独打包则标出assetbundle名 for (int i = 0; i < allTarget.Count; i++) { ABTarget target = allTarget[i]; AssetImporter importer = AssetImporter.GetAtPath(target.assetPath); if (!importer) { continue; } importer.assetBundleName = target.needSelfExport ? target.bundleName : null; } var bundleSavePath = ABExportConst.PlatformBundleSavePath + "/" + exportDir; PathEx.MakeDirectoryExist(bundleSavePath); AssetDatabase.Refresh(); //开始打包 BuildPipeline.BuildAssetBundles(bundleSavePath, BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget); //清除所有 asset bundle name for (int i = 0; i < allTarget.Count; i++) { ABTarget target = allTarget[i]; if (!target.needSelfExport) { continue; } AssetImporter importer = AssetImporter.GetAtPath(target.assetPath); if (!importer) { continue; } importer.assetBundleName = null; } }
/// <summary> /// 保存依赖文件 /// </summary> /// <param name="fliter"></param> private void SaveDep(string exportDirectory) { var all = context.allTarget; var path = PathEx.Combine(ABExportConst.PlatformBundleSavePath, exportDirectory, ABPathResolver.DEPEND_FILE_NAME); if (File.Exists(path)) { File.Delete(path); } List <ABTarget> exportList = new List <ABTarget>(); for (int i = 0; i < all.Count; i++) { ABTarget target = all[i]; if (target.needSelfExport) { exportList.Add(target); } } dataWriter.Save(path, exportList.ToArray()); }
/// <summary> /// 分析关系依赖 /// </summary> public void Analyze() { if (isAnalyzed) { return; } isAnalyzed = true; //得到依赖 UnityEngine.Object[] deps = EditorUtility.CollectDependencies(new UnityEngine.Object[] { asset }); var depList = from dep in deps let path = AssetDatabase.GetAssetPath(dep) where !(dep is MonoScript || path.StartsWith("Resources")) select AssetDatabase.GetAssetPath(dep); string[] paths = depList.Distinct().ToArray(); paths.Foreach <string>((path) => { if (!File.Exists(path)) { return; } FileInfo fileInfo = new FileInfo(path); ABTarget target = GetOrCreateTarget(context, fileInfo); if (target == null) { return; } AddDepend(target); target.Analyze(); }); }
/// <summary> /// 尝试获取ABTarget /// </summary> /// <param name="assetPath"></param> /// <param name="target"></param> /// <returns></returns> public bool TryGetTarget(string assetPath, out ABTarget target) { return(assetPath2target.TryGetValue(assetPath, out target)); }
/// <summary> /// 尝试获取ABTarget /// </summary> /// <param name="instanceId"></param> /// <param name="target"></param> /// <returns></returns> public bool TryGetTarget(int instanceId, out ABTarget target) { return(object2target.TryGetValue(instanceId, out target)); }
/// <summary> /// 将Target从上下文中移除 /// </summary> /// <param name="target"></param> public static void RemoveTarget(ABTarget target) { target.context.RemoveTarget(target); }
/// <summary> /// 从依赖本对象的依赖列表中移除 /// </summary> /// <param name="target"></param> private void RemoveReverseDepend(ABTarget target) { target.RemoveDepend(this); }
/// <summary> /// 移除本对象的依赖项 /// </summary> /// <param name="target"></param> private void RemoveDepend(ABTarget target) { dependencies.Remove(target); target.reverseDependencies.Remove(this); }
/// <summary> /// 添加Target /// </summary> /// <param name="target"></param> public void AddTarget(ABTarget target) { assetPath2target[target.assetPath] = target; object2target[target.asset.GetInstanceID()] = target; }
/// <summary> /// 移除Target /// </summary> /// <param name="target"></param> public void RemoveTarget(ABTarget target) { assetPath2target.Remove(target.assetPath); object2target.Remove(target.asset.GetInstanceID()); }
/// <summary> /// 向依赖本对象的依赖列表中添加项 /// </summary> /// <param name="target"></param> private void AddReverseDepend(ABTarget target) { target.AddDepend(this); }