Unity AssetDatabase类中提供了获取资产依赖项的API,如果我们想要获取某一资产被哪些资产引用,可以通过如下思路去实现:
1.获取工程中的所有资产;
2.遍历每一项资产,获取其依赖项列表;
3.如果资产A的依赖项列表中包含资产B,则资产B被资产A引用。
用到的核心API:
1.根据guid获取资产路径
//// 摘要:// Gets the corresponding asset path for the supplied GUID, or an empty string if// the GUID can't be found.//// 参数:// guid:// The GUID of an asset.//// 返回结果:// Path of the asset relative to the project folder.publicstaticstringGUIDToAssetPath(stringguid) { returnGUIDToAssetPath_Internal(newGUID(guid)); }
2.根据资产路径获取资产的类型
//// 摘要:// Returns the type of the main asset object at assetPath.//// 参数:// assetPath:// Filesystem path of the asset to load.[MethodImpl(MethodImplOptions.InternalCall)] publicstaticexternTypeGetMainAssetTypeAtPath(stringassetPath);
3.根据资产路径获取该资产的依赖项:
//// 摘要:// Returns an array of all the assets that are dependencies of the asset at the// specified pathName. Note: GetDependencies() gets the Assets that are referenced// by other Assets. For example, a Scene could contain many GameObjects with a Material// attached to them. In this case, GetDependencies() will return the path to the// Material Assets, but not the GameObjects as those are not Assets on your disk.//// 参数:// pathName:// The path to the asset for which dependencies are required.//// recursive:// Controls whether this method recursively checks and returns all dependencies// including indirect dependencies (when set to true), or whether it only returns// direct dependencies (when set to false).//// 返回结果:// The paths of all assets that the input depends on.publicstaticstring[] GetDependencies(stringpathName) { returnGetDependencies(pathName, recursive: true); }
4.根据资产路径及类型加载资产
//// 摘要:// Returns the first asset object of type type at given path assetPath.//// 参数:// assetPath:// Path of the asset to load.//// type:// Data type of the asset.//// 返回结果:// The asset matching the parameters.[MethodImpl(MethodImplOptions.InternalCall)] [NativeThrows] [PreventExecutionInState(AssetDatabasePreventExecution.kGatheringDependenciesFromSourceFile, PreventExecutionSeverity.PreventExecution_ManagedException, "Assets may not be loaded while dependencies are being gathered, as these assets may not have been imported yet.")] [TypeInferenceRule(TypeInferenceRules.TypeReferencedBySecondArgument)] publicstaticexternUnityEngine.ObjectLoadAssetAtPath(stringassetPath, Typetype);
下面实现的工具,既可以获取资产的依赖项,也可以获取资产的引用项:
代码如下:
usingSystem; usingUnityEngine; usingUnityEditor; usingSystem.Linq; usingSystem.Collections.Generic; namespaceSK.Framework{ publicclassAssetsStatistics : EditorWindow { [MenuItem("SKFramework/Assets Statistics")] privatestaticvoidOpen() { GetWindow<AssetsStatistics>("Assets Statistics").Show(); } privateVector2selectedListScroll; //当前选中项索引privateintcurrentSelectedIndex=-1; privateenumMode { Dependence, Reference, } privateModemode=Mode.Dependence; privateVector2dependenceListScroll; privateVector2referenceListScroll; privatestring[] dependenciesArray; privatestring[] referenceArray; privatevoidOnGUI() { OnListGUI(); OnMenuGUI(); } privatevoidOnListGUI() { if (Selection.assetGUIDs.Length==0) return; selectedListScroll=EditorGUILayout.BeginScrollView(selectedListScroll); for (inti=0; i<Selection.assetGUIDs.Length; i++) { //通过guid获取资产路径stringpath=AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]); GUILayout.BeginHorizontal(currentSelectedIndex==i?"SelectionRect" : "dragtab first"); //获取资产类型Typetype=AssetDatabase.GetMainAssetTypeAtPath(path); GUILayout.Label(EditorGUIUtility.IconContent(GetIconName(type.Name)), GUILayout.Width(20f), GUILayout.Height(15f)); GUILayout.Label(path); //点击选中if(Event.current.type==EventType.MouseDown&&GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition)) { currentSelectedIndex=i; Event.current.Use(); GetDependencies(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); } privatevoidOnMenuGUI() { GUILayout.FlexibleSpace(); GUILayout.BeginVertical("Box", GUILayout.Height(position.height* .7f)); { GUILayout.BeginHorizontal(); { Colorcolor=GUI.color; GUI.color=mode==Mode.Dependence?color : Color.gray; if (GUILayout.Button("依赖", "ButtonLeft")) { mode=Mode.Dependence; } GUI.color=mode==Mode.Reference?color : Color.gray; if (GUILayout.Button("引用", "ButtonRight")) { mode=Mode.Reference; } GUI.color=color; } GUILayout.EndHorizontal(); switch (mode) { caseMode.Dependence: OnDependenceGUI(); break; caseMode.Reference: OnReferenceGUI(); break; } } GUILayout.EndVertical(); } privatevoidGetDependencies() { stringguid=Selection.assetGUIDs[currentSelectedIndex]; stringpath=AssetDatabase.GUIDToAssetPath(guid); dependenciesArray=AssetDatabase.GetDependencies(path); } privatevoidOnDependenceGUI() { EditorGUILayout.HelpBox("该资产的依赖项", MessageType.Info); if (currentSelectedIndex!=-1) { dependenceListScroll=EditorGUILayout.BeginScrollView(dependenceListScroll); for (inti=0; i<dependenciesArray.Length; i++) { stringdependency=dependenciesArray[i]; GUILayout.BeginHorizontal("dragtab first"); Typetype=AssetDatabase.GetMainAssetTypeAtPath(dependency); GUILayout.Label(EditorGUIUtility.IconContent(GetIconName(type.Name)), GUILayout.Width(20f), GUILayout.Height(15f)); GUILayout.Label(dependency); if (Event.current.type==EventType.MouseDown&&GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition)) { varobj=AssetDatabase.LoadAssetAtPath(dependency, type); EditorGUIUtility.PingObject(obj); Event.current.Use(); } GUILayout.EndHorizontal(); } EditorGUILayout.EndScrollView(); } } privatevoidOnReferenceGUI() { EditorGUILayout.HelpBox("该资产的引用项(需点击刷新按钮获取,需要一定时间)", MessageType.Info); GUI.enabled=currentSelectedIndex!=-1; if (GUILayout.Button("刷新")) { if (EditorUtility.DisplayDialog("提醒", "获取工程资产之间的引用关系需要一定时间,是否确定开始", "确定", "取消")) { Dictionary<string, string[]>referenceDic=newDictionary<string, string[]>(); string[] paths=AssetDatabase.GetAllAssetPaths(); for (inti=0; i<paths.Length; i++) { referenceDic.Add(paths[i], AssetDatabase.GetDependencies(paths[i])); EditorUtility.DisplayProgressBar("进度", "获取工程资产之间的依赖关系", i+1/paths.Length); } EditorUtility.ClearProgressBar(); stringguid=Selection.assetGUIDs[currentSelectedIndex]; stringpath=AssetDatabase.GUIDToAssetPath(guid); referenceArray=referenceDic.Where(m=>m.Value.Contains(path)).Select(m=>m.Key).ToArray(); } } GUI.enabled=true; if(referenceArray!=null) { referenceListScroll=EditorGUILayout.BeginScrollView(referenceListScroll); { for (inti=0; i<referenceArray.Length; i++) { stringreference=referenceArray[i]; GUILayout.BeginHorizontal("dragtab first"); Typetype=AssetDatabase.GetMainAssetTypeAtPath(reference); GUILayout.Label(EditorGUIUtility.IconContent(GetIconName(type.Name)), GUILayout.Width(20f), GUILayout.Height(15f)); GUILayout.Label(reference); if (Event.current.type==EventType.MouseDown&&GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition)) { varobj=AssetDatabase.LoadAssetAtPath(reference, type); EditorGUIUtility.PingObject(obj); Event.current.Use(); } GUILayout.EndHorizontal(); } } EditorGUILayout.EndScrollView(); } } privatestringGetIconName(stringtypeName) { switch (typeName) { case"Material": return"d_Material Icon"; case"Mesh": return"d_Mesh Icon"; case"AnimationClip": return"d_AnimationClip Icon"; case"GameObject": return"d_Prefab Icon"; case"Texture2D": return"d_Texture Icon"; case"MonoScript": return"d_cs Script Icon"; case"AnimatorController": return"d_AnimatorController Icon"; case"DefaultAsset": return"d_DefaultAsset Icon"; case"TextAsset": return"d_TextAsset Icon"; case"TimelineAsset": return"d_UnityEditor.Timeline.TimelineWindow"; default: return"d__Help@2x"; } } privatevoidOnSelectionChange() { currentSelectedIndex=-1; Repaint(); } } }