您当前的位置: 首页 >  unity

CoderZ1010

暂无认证

  • 4浏览

    0关注

    168博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Unity 编辑器开发实战【AssetDatabase】- 获取资产的依赖项、引用项

CoderZ1010 发布时间:2022-03-28 15:40:33 ,浏览量:4

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.
public static string GUIDToAssetPath(string guid)
{
    return GUIDToAssetPath_Internal(new GUID(guid));
}

2.根据资产路径获取资产的类型

//
// 摘要:
//     Returns the type of the main asset object at assetPath.
//
// 参数:
//   assetPath:
//     Filesystem path of the asset to load.
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern Type GetMainAssetTypeAtPath(string assetPath);

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.
public static string[] GetDependencies(string pathName)
{
    return GetDependencies(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)]
public static extern UnityEngine.Object LoadAssetAtPath(string assetPath, Type type);

下面实现的工具,既可以获取资产的依赖项,也可以获取资产的引用项:

代码如下:

using System;
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Collections.Generic;

namespace SK.Framework
{
    public class AssetsStatistics : EditorWindow
    {
        [MenuItem("SKFramework/Assets Statistics")]
        private static void Open()
        {
            GetWindow("Assets Statistics").Show();
        }

        private Vector2 selectedListScroll;
        //当前选中项索引
        private int currentSelectedIndex = -1;

        private enum Mode
        {
            Dependence,
            Reference,
        }
        private Mode mode = Mode.Dependence;

        private Vector2 dependenceListScroll;
        private Vector2 referenceListScroll;

        private string[] dependenciesArray;
        private string[] referenceArray;

        private void OnGUI()
        {
            OnListGUI();

            OnMenuGUI();
        }

        private void OnListGUI()
        {
            if (Selection.assetGUIDs.Length == 0) return;
            selectedListScroll = EditorGUILayout.BeginScrollView(selectedListScroll);
            for (int i = 0; i < Selection.assetGUIDs.Length; i++)
            {
                //通过guid获取资产路径
                string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]);
                GUILayout.BeginHorizontal(currentSelectedIndex == i ? "SelectionRect" : "dragtab first");
                //获取资产类型
                Type type = 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();
        }
        private void OnMenuGUI()
        {
            GUILayout.FlexibleSpace();

            GUILayout.BeginVertical("Box", GUILayout.Height(position.height * .7f));
            {
                GUILayout.BeginHorizontal();
                {
                    Color color = 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)
                {
                    case Mode.Dependence: OnDependenceGUI(); break;
                    case Mode.Reference: OnReferenceGUI(); break;
                }
            }
            GUILayout.EndVertical();
        }
        private void GetDependencies()
        {
            string guid = Selection.assetGUIDs[currentSelectedIndex];
            string path = AssetDatabase.GUIDToAssetPath(guid);
            dependenciesArray = AssetDatabase.GetDependencies(path);
        }
        private void OnDependenceGUI()
        {
            EditorGUILayout.HelpBox("该资产的依赖项", MessageType.Info);
            if (currentSelectedIndex != -1)
            {
                dependenceListScroll = EditorGUILayout.BeginScrollView(dependenceListScroll);
                for (int i = 0; i < dependenciesArray.Length; i++)
                {
                    string dependency = dependenciesArray[i];
                    GUILayout.BeginHorizontal("dragtab first");
                    Type type = 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))
                    {
                        var obj = AssetDatabase.LoadAssetAtPath(dependency, type);
                        EditorGUIUtility.PingObject(obj);
                        Event.current.Use();
                    }
                    GUILayout.EndHorizontal();
                }
                EditorGUILayout.EndScrollView();
            }
        }
        private void OnReferenceGUI()
        {
            EditorGUILayout.HelpBox("该资产的引用项(需点击刷新按钮获取,需要一定时间)", MessageType.Info);

            GUI.enabled = currentSelectedIndex != -1;
            if (GUILayout.Button("刷新")) 
            {
                if (EditorUtility.DisplayDialog("提醒", "获取工程资产之间的引用关系需要一定时间,是否确定开始", "确定", "取消"))
                {
                    Dictionary referenceDic = new Dictionary();
                    string[] paths = AssetDatabase.GetAllAssetPaths();
                    for (int i = 0; i < paths.Length; i++)
                    {
                        referenceDic.Add(paths[i], AssetDatabase.GetDependencies(paths[i]));
                        EditorUtility.DisplayProgressBar("进度", "获取工程资产之间的依赖关系", i + 1 / paths.Length);
                    }
                    EditorUtility.ClearProgressBar();
                    string guid = Selection.assetGUIDs[currentSelectedIndex];
                    string path = 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 (int i = 0; i < referenceArray.Length; i++)
                    {
                        string reference = referenceArray[i];
                        GUILayout.BeginHorizontal("dragtab first");
                        Type type = 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))
                        {
                            var obj = AssetDatabase.LoadAssetAtPath(reference, type);
                            EditorGUIUtility.PingObject(obj);
                            Event.current.Use();
                        }
                        GUILayout.EndHorizontal();
                    }
                }
                EditorGUILayout.EndScrollView();
            }
        }
        private string GetIconName(string typeName)
        {
            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";
            }
        }
        private void OnSelectionChange()
        {
            currentSelectedIndex = -1;
            Repaint();
        }
    }
}
关注
打赏
1653184800
查看更多评论
立即登录/注册

微信扫码登录

0.0734s