Unity Editor扩展——查找UI预设中用到的所有图集

效果图:

 代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
using LuaFramework;

/// <summary>
/// 查找UI预设中用到的所有图集
/// </summary>
public class AtlasInUIPrefabTool : EditorWindow
{
    [MenuItem("查找/列出所有UI预设对图集的引用", false, 131)]
    public static void open()
    {
        var win = GetWindow<AtlasInUIPrefabTool>();
        win.Show();
    }

    private List<UIPrefabInfo> uIPrefabInfos = new List<UIPrefabInfo>();
    private Vector2 scrolPos = Vector2.zero;

    private void OnGUI()
    {
        GUILayout.Space(10);
        GUILayout.Label("功能说明:列出所有UI预设对图集的引用。");

        GUILayout.Space(10);
        GUILayout.BeginHorizontal();
        if (GUILayout.Button("刷新数据"))
        {
            CheckAtlasReference();
        }
        if (GUILayout.Button("清除数据"))
        {
            uIPrefabInfos.Clear();
        }
        GUILayout.EndHorizontal();

        GUILayout.Space(10);
        if (uIPrefabInfos == null || uIPrefabInfos.Count <= 0)
        {
            GUILayout.Label("has nothing to show");
        }
        else
        {
            scrolPos = GUILayout.BeginScrollView(scrolPos);
            for (int idx = 0; idx < uIPrefabInfos.Count; idx++)
            {
                uIPrefabInfos[idx].ShowGui();
            }
            GUILayout.EndScrollView();
        }
    }

    private void CheckAtlasReference()
    {
        uIPrefabInfos.Clear();

        List<string> folders = EditorCommonUtils.NGUIPrefabFoldersList();
        string path;
        DirectoryInfo dirInfo;
        FileInfo[] fileInfos;
        string filePath;
        for (int idx = 0; idx < folders.Count; idx++)
        {
            path = folders[idx];
            path = string.Format("{0}{1}", Application.dataPath.Substring(0, Application.dataPath.Length - 6), path);
            dirInfo = new DirectoryInfo(path);
            if (dirInfo.Exists == false)
            {
                Debug.LogErrorFormat("目录不存在:{0}", path);
                continue;
            }

            fileInfos = dirInfo.GetFiles("*.prefab", SearchOption.AllDirectories);
            for (int fileIdx = 0; fileIdx < fileInfos.Length; fileIdx++)
            {
                filePath = fileInfos[fileIdx].FullName;
                filePath = filePath.Replace("\\", "/");
                filePath = filePath.Substring(Application.dataPath.Length - 6);
                EditorUtility.DisplayProgressBar("进度", filePath, (float)fileIdx / fileInfos.Length);

                UIPrefabInfo uiPrefabInfo = CheckPrefab(filePath);
                if (uiPrefabInfo != null && uiPrefabInfo.atlasInfos.Count > 0)
                {
                    uIPrefabInfos.Add(uiPrefabInfo);
                }
            }
        }
        EditorUtility.ClearProgressBar();

        uIPrefabInfos.Sort(delegate (UIPrefabInfo uiPrefabInfo1, UIPrefabInfo uiPrefabInfo2)
        {
            return uiPrefabInfo1.prefabPath.CompareTo(uiPrefabInfo2.prefabPath);
        });
    }

    private UIPrefabInfo CheckPrefab(string assetPath)
    {
        AssetImporter assetImporter = AssetImporter.GetAtPath(assetPath);
        if (string.IsNullOrEmpty(assetImporter.assetBundleName))
        {
            //未设置assetbundle name
            return null;
        }

        UIPrefabInfo uiPrefabInfo = new UIPrefabInfo() { prefabPath = assetPath };

        GameObject prefabGo = AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject)) as GameObject;
        string childPath;

        UISprite[] uISprites = prefabGo.transform.GetComponentsInChildren<UISprite>(true);
        for (int idx = 0; idx < uISprites.Length; idx++)
        {
            if (uISprites[idx].atlas == null) continue;

            childPath = null;
            GetChildPath(prefabGo.transform, uISprites[idx].transform, ref childPath);
            uiPrefabInfo.AddAtlasPoint(uISprites[idx].atlas, childPath);
        }

        return uiPrefabInfo;
    }
    private void GetChildPath(Transform root, Transform child, ref string path)
    {
        if (string.IsNullOrEmpty(path))
            path = child.name;
        else
            path = string.Format("{0}/{1}", child.name, path);

        if (child != root && child.parent != null)
        {
            child = child.parent;
            GetChildPath(root, child, ref path);
        }
    }


    public class UIPrefabInfo
    {
        private List<string> specialAtlas = new List<string>() { "Tutorial", "ShopAndRecruit", "LoadingAtlas", "HeroSkillIcon", "HeroAttributeIcon", "CardSmallAtlas", "Card_Resource_One", "AvatarAtlas" };

        public string prefabPath;
        public bool hasOldAtlas = false;
        public List<UIPrefabAtlasInfo> atlasInfos = new List<UIPrefabAtlasInfo>();

        private bool showAll = false;

        public void AddAtlasPoint(UIAtlas uiAtlas, string childPath)
        {
            if (uiAtlas == null) return;

            string atlasPath = AssetDatabase.GetAssetPath(uiAtlas);
            UIPrefabAtlasInfo uiPrefabAtlasInfo = atlasInfos.Find(delegate (UIPrefabAtlasInfo atlasInfo)
            {
                return atlasInfo.atlasPath.Equals(atlasPath, System.StringComparison.Ordinal);
            });
            if (uiPrefabAtlasInfo == null)
            {
                uiPrefabAtlasInfo = new UIPrefabAtlasInfo() { atlasPath = atlasPath };
                //是否是旧目录的图集
                if (atlasPath.IndexOf("Assets/Starwars/Builds/Atlas", System.StringComparison.Ordinal) >= 0 && specialAtlas.Contains(uiAtlas.name) == false)
                {
                    hasOldAtlas = true;
                    uiPrefabAtlasInfo.isOldAtlas = true;
                }

                atlasInfos.Add(uiPrefabAtlasInfo);
                //按名称排序
                atlasInfos.Sort(delegate (UIPrefabAtlasInfo atlasInfo1, UIPrefabAtlasInfo atlasInfo2)
                {
                    return atlasInfo1.atlasPath.CompareTo(atlasInfo2.atlasPath);
                });
            }
            uiPrefabAtlasInfo.AddPoint(childPath);
        }

        public void ShowGui()
        {
            if (hasOldAtlas) GUI.color = Color.yellow;
            showAll = EditorGUILayout.Foldout(showAll, prefabPath);
            GUI.color = Color.white;

            if (showAll)
            {
                GUILayout.Space(5);
                GUILayout.BeginHorizontal();
                GUILayout.Space(50);
                GUILayout.BeginVertical();

                for (int idx = 0; idx < atlasInfos.Count; idx++)
                    atlasInfos[idx].ShowGui();

                GUILayout.EndVertical();
                GUILayout.EndHorizontal();
            }
        }
    }

    public class UIPrefabAtlasInfo
    {
        public string atlasPath;
        public bool isOldAtlas = false;
        public List<string> childPoints = new List<string>();

        private bool showAll = false;

        public void AddPoint(string childPath)
        {
            if (childPoints.IndexOf(childPath) < 0)
            {
                childPoints.Add(childPath);
                childPoints.Sort();
            }
        }

        public void ShowGui()
        {
            if (isOldAtlas) GUI.color = Color.yellow;
            showAll = EditorGUILayout.Foldout(showAll, atlasPath);
            GUI.color = Color.white;

            if (showAll)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Space(50);
                GUILayout.BeginVertical();

                for (int idx = 0; idx < childPoints.Count; idx++)
                {
                    GUILayout.Space(5);
                    GUILayout.Label(childPoints[idx]);
                }

                GUILayout.EndVertical();
                GUILayout.EndHorizontal();
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

/// <summary>
/// 编译器辅助器
/// </summary>
class EditorCommonUtils
{
    /// <summary>
    /// UI预设目录
    /// </summary>
    /// <returns></returns>
    public static List<string> NGUIPrefabFoldersList()
    {
        List<string> res = new List<string>();
        res.Add("Assets");
        return res;
    }
}

Unity Editor扩展是指通过编写代码来扩展Unity编辑器的功能。通过创建自定义的编辑器窗口、工具栏按钮、菜单项和面板等,开发者可以为自己的项目添加一些定制化功能,以提高开发效率和用户体验。 Unity提供了一套API来实现编辑器扩展,开发者可以利用这些API去创建自定义的编辑器界面。首先,我们需要创建一个继承自EditorWindow或Editor类的脚本,然后在这个脚本实现我们想要的功能。比如,我们可以在自定义的编辑器窗口创建一些GUI元素,如按钮、文本框、下拉菜单等,用于控制场景的对象、调整参数或执行特定的操作。 另外,Unity还提供了一些常用的工具类,如SerializedObject、SerializedProperty等,以便开发者可以访问和修改Unity对象的属性。使用这些工具类,我们可以在编辑器扩展实现对象的序列化、反序列化和检查等功能。 在开发过程Unity的编辑器扩展还可以与自定义的脚本进行交互。通过注册自定义的菜单项、工具栏按钮或快捷键,我们可以在编辑器快速调用脚本的功能,并在自定义界面显示脚本的运行结果。 总结来说,Unity Editor扩展是一种强大的工具,它可以帮助开发者提高开发效率和用户体验。通过编写代码,我们可以创建出各种各样的自定义编辑器界面,以满足不同项目的需求。无论是增加交互性、优化工作流程还是增加特定的功能,Unity的编辑器扩展都能提供灵活和强大的解决方案。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值