/// <summary> /// 动画控制器比较特殊,不能通过序列化得到 /// </summary> /// <param name="info"></param> /// <param name="o"></param> private static void AnalyzeObjectReference2(AssetBundleFileInfo info, Object o) { AnimatorController ac = o as AnimatorController; if (ac) { #if UNITY_5 || UNITY_5_3_OR_NEWER foreach (var clip in ac.animationClips) { AnalyzeObjectReference(info, clip); } #else List <State> list = new List <State>(); for (int i = 0; i < ac.layerCount; i++) { AnimatorControllerLayer layer = ac.GetLayer(i); list.AddRange(AnimatorStateMachine_StatesRecursive(layer.stateMachine)); } foreach (State state in list) { var clip = state.GetMotion() as AnimationClip; if (clip) { AnalyzeObjectReference(info, clip); } } #endif } }
/// <summary> /// 直接递归所有文件 /// </summary> /// <param name="directoryPath"></param> /// <returns></returns> private static List <AssetBundleFileInfo> AnalyzAllFiles(string directoryPath) { List <AssetBundleFileInfo> infos = new List <AssetBundleFileInfo>(); string bom = "Unity"; char[] flag = new char[5]; string[] files = Directory.GetFiles(directoryPath, "*", SearchOption.AllDirectories); foreach (var file in files) { using (StreamReader streamReader = new StreamReader(file)) { if (streamReader.Read(flag, 0, flag.Length) == flag.Length && new string(flag) == bom) { AssetBundleFileInfo info = new AssetBundleFileInfo { name = file.Substring(directoryPath.Length + 1), path = file, rootPath = directoryPath, size = streamReader.BaseStream.Length, directDepends = new string[] { }, allDepends = new string[] { } }; infos.Add(info); } } } return(infos); }
/// <summary> /// 分析对象的引用 /// </summary> /// <param name="info"></param> /// <param name="o"></param> public static void AnalyzeObjectReference(AssetBundleFileInfo info, Object o) { if (o == null || info.objDict.ContainsKey(o)) { return; } var serializedObject = new SerializedObject(o); info.objDict.Add(o, serializedObject); if (inspectorMode == null) { inspectorMode = typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance); } inspectorMode.SetValue(serializedObject, InspectorMode.Debug, null); var it = serializedObject.GetIterator(); while (it.NextVisible(true)) { if (it.propertyType == SerializedPropertyType.ObjectReference && it.objectReferenceValue != null) { AnalyzeObjectReference(info, it.objectReferenceValue); } } // 只能用另一种方式获取的引用 AnalyzeObjectReference2(info, o); }
public static void AnalyzeObjectsCompleted(AssetBundleFileInfo info) { foreach (var kv in info.objDict) { AssetBundleFilesAnalyzeObject.ObjectAddToFileInfo(kv.Key, kv.Value, info); kv.Value.Dispose(); } info.objDict.Clear(); }
public void AddBundleSceneInfo(AssetBundleFileInfo info, string[] scenePaths) { #if UNITY_5_4_OR_NEWER foreach (var scenePath in scenePaths) { m_BundleSceneInfos.Enqueue(new BundleSceneInfo() { fileInfo = info, sceneName = Path.GetFileNameWithoutExtension(scenePath), scenePath = scenePath }); } #endif }
/// <summary> /// 分析Unity5方式的依赖构成 /// </summary> /// <param name="directoryPath"></param> /// <returns></returns> private static List <AssetBundleFileInfo> AnalyzeManifestDepend(string directoryPath) { string manifestName = Path.GetFileName(directoryPath); string manifestPath = Path.Combine(directoryPath, manifestName); if (!File.Exists(manifestPath)) { Debug.LogWarning(manifestPath + " is not exists! Use AnalyzAllFiles ..."); return(null); } #if UNITY_5_3_OR_NEWER AssetBundle manifestAb = AssetBundle.LoadFromFile(manifestPath); #else AssetBundle manifestAb = AssetBundle.CreateFromMemoryImmediate(File.ReadAllBytes(manifestPath)); #endif if (!manifestAb) { Debug.LogError(manifestPath + " ab load faild!"); return(null); } List <AssetBundleFileInfo> infos = new List <AssetBundleFileInfo>(); #if UNITY_5 || UNITY_5_3_OR_NEWER AssetBundleManifest assetBundleManifest = manifestAb.LoadAsset <AssetBundleManifest>("assetbundlemanifest"); var bundles = assetBundleManifest.GetAllAssetBundles(); foreach (var bundle in bundles) { string path = Path.Combine(directoryPath, bundle); AssetBundleFileInfo info = new AssetBundleFileInfo { name = bundle, path = path, rootPath = directoryPath, size = new FileInfo(path).Length, directDepends = assetBundleManifest.GetDirectDependencies(bundle), allDepends = assetBundleManifest.GetAllDependencies(bundle) }; infos.Add(info); } #endif manifestAb.Unload(true); return(infos); }
private static void FillAssetByType(AssetBundleFileInfo info, string type, ExcelWorksheet ws, ref int startRow) { int count = info.GetAssetCount(type); if (count == 0) { return; } startRow++; ws.Cells[startRow, 1].Value = type + " (" + count + ")"; SetRangeStyle(ws.Cells[startRow, 1, startRow, 4]); Color redColor = ColorTranslator.FromHtml("#FF0049"); int startCol = 1; foreach (var fileInfo in info.assets) { if (fileInfo.type == type) { if (startCol == 1) { startRow++; } ws.Cells[startRow, startCol].Value = fileInfo.name; ws.Cells[startRow, startCol].Hyperlink = fileInfo.detailHyperLink; // 冗余则红色显示 if (fileInfo.includedBundles.Count > 1 && fileInfo.type != AssetFileInfoType.monoScript) { ws.Cells[startRow, startCol].Style.Font.Color.SetColor(redColor); } startCol++; if (startCol > 4) { startCol = 1; } } } }
/// <summary> /// 分析脚本的引用(这只在脚本在工程里时才有效) /// </summary> /// <param name="info"></param> /// <param name="o"></param> public static void AnalyzeObjectComponent(AssetBundleFileInfo info, Object o) { var go = o as GameObject; if (!go) { return; } var components = go.GetComponentsInChildren <Component>(true); foreach (var component in components) { if (!component) { continue; } AnalyzeObjectReference(info, component); } }
private static void FillAssetDepends(AssetBundleFileInfo info, ExcelWorksheet ws, ref int startRow) { if (info.allDepends == null && info.beDepends == null) { return; } if (info.allDepends != null && info.beDepends != null && info.allDepends.Length == 0 && info.beDepends.Length == 0) { return; } int rowAdd = 0; int titleRow = ++startRow; if (info.allDepends != null && info.allDepends.Length != 0) { ws.Cells[titleRow, 3].Value = "它依赖哪些AssetBundle文件? (" + info.allDepends.Length + ")"; SetRangeStyle(ws.Cells[titleRow, 3, titleRow, 4]); int dependRow = titleRow; foreach (var depend in info.allDepends) { if (string.IsNullOrEmpty(depend)) { continue; } dependRow++; var dependInfo = AssetBundleFilesAnalyze.GetAssetBundleFileInfo(depend); ws.Cells[dependRow, 3].Value = dependInfo.name; ws.Cells[dependRow, 3].Hyperlink = dependInfo.detailHyperLink; ws.Cells[dependRow, 3, dependRow, 4].Merge = true; } rowAdd = dependRow - titleRow; } if (info.beDepends != null && info.beDepends.Length != 0) { ws.Cells[titleRow, 1].Value = "哪些AssetBundle文件依赖它? (" + info.beDepends.Length + ")"; SetRangeStyle(ws.Cells[titleRow, 1, titleRow, 2]); int dependRow = titleRow; foreach (var depend in info.beDepends) { dependRow++; var dependInfo = AssetBundleFilesAnalyze.GetAssetBundleFileInfo(depend); ws.Cells[dependRow, 1].Value = dependInfo.name; ws.Cells[dependRow, 1].Hyperlink = dependInfo.detailHyperLink; ws.Cells[dependRow, 1, dependRow, 2].Merge = true; } int rowAdd2 = dependRow - titleRow; if (rowAdd2 > rowAdd) { rowAdd = rowAdd2; } } startRow += rowAdd; }
public static void ObjectAddToFileInfo(Object o, SerializedObject serializedObject, AssetBundleFileInfo info) { if (!o) { return; } string name2 = o.name; string type = o.GetType().ToString(); if (type.StartsWith("UnityEngine.")) { type = type.Substring(12); // 如果是内置的组件,就不当作是资源 if (o as Component) { return; } } else if (type == "UnityEditor.Animations.AnimatorController") { type = "AnimatorController"; } else if (type == "UnityEditorInternal.AnimatorController") { type = "AnimatorController"; } else if (type == "UnityEditor.MonoScript") { MonoScript ms = o as MonoScript; string type2 = ms.GetClass().ToString(); if (type2.StartsWith("UnityEngine.")) { // 内置的脚本对象也不显示出来 return; } // 外部的组件脚本,保留下来 type = "MonoScript"; } else { // 外部的组件脚本,走上面的MonoScript if (o as Component) { return; } // 外部的序列化对象,已经被脚本给分析完毕了,不需要再添加进来 if (o as ScriptableObject) { return; } Debug.LogError("What's this? " + type); return; } // 内建的资源排除掉 string assetPath = AssetDatabase.GetAssetPath(o); if (!string.IsNullOrEmpty(assetPath)) { return; } long guid; if (info.isScene) { // 场景的话,没法根据PathID来确定唯一性,那么就认为每个场景用到的资源都不一样 guid = (info.name + name2 + type).GetHashCode(); } else { SerializedProperty pathIdProp = serializedObject.FindProperty("m_LocalIdentfierInFile"); #if UNITY_5 || UNITY_5_3_OR_NEWER guid = pathIdProp.longValue; #else guid = pathIdProp.intValue; #endif } if (info.IsAssetContain(guid)) { return; } AssetFileInfo info2 = AssetBundleFilesAnalyze.GetAssetFileInfo(guid); info2.name = name2; info2.type = type; info2.includedBundles.Add(info); if (info2.detailHyperLink == null) { // 初次创建对象时链接为空 info2.detailHyperLink = new OfficeOpenXml.ExcelHyperLink(System.String.Empty, info2.name); info2.propertys = AnalyzeObject(o, serializedObject, info.rootPath, info.name); } info.assets.Add(info2); }