脚本丢失查询及清理

#if UNITY_EDITOR
namespace Fury.Editor
{
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    using UnityEditor;

    public class MissingReferenceFinder : EditorWindow
    {

        private Vector2 scrollPos = Vector2.zero;
        GUIStyle headStyle = new GUIStyle();

        private int selectedButtonIndex = -1;

        private Color selectedColor = Color.white;

        public List<Result> results = new List<Result>();
        [MenuItem("工具箱/一键移除丢失脚本")]
        public static void ShowWindow()
        {
            MissingReferenceFinder window = GetWindow<MissingReferenceFinder>();
            window.titleContent = new GUIContent("MissingReferenceFinder");
            window.Show();
        }


        private void OnEnable()
        {
            headStyle.fontSize = 15;
            headStyle.fontStyle = FontStyle.Bold;
            headStyle.alignment = TextAnchor.MiddleCenter;
            headStyle.normal.textColor = Color.white;
        }

        public void OnGUI()
        {
            EditorGUILayout.BeginVertical(GUILayout.Width(position.width), GUILayout.Height(position.height));
            {
                GUILayout.Space(10); // Add gap before the heading

                DrawLabel("一键移除丢失脚本", headStyle);

                GUILayout.Space(10); // Add gap after the heading

                EditorGUILayout.BeginHorizontal();
                {
                    if (GUILayout.Button("搜索资源文件夹", GetButtonStyle(0)))
                    {
                        selectedButtonIndex = 0;
                        SearchAssetFolder();
                    }

                    if (GUILayout.Button("搜索当前场景", GetButtonStyle(1)))
                    {
                        selectedButtonIndex = 1;
                        SearchCurrentScene();
                    }

                    if (GUILayout.Button("搜索选中的物体", GetButtonStyle(2)))
                    {
                        selectedButtonIndex = 2;
                        SerachSelectedAsset();
                    }
                }
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.BeginVertical(EditorStyles.helpBox, GUILayout.Width(position.width - 5), GUILayout.Height(position.height - 105));
                {
                    scrollPos = EditorGUILayout.BeginScrollView(scrollPos); // Adding scroll view for the Components List
                    {
                        foreach (var item in results)
                        {
                            EditorGUILayout.ObjectField(item.Obj, typeof(GameObject), true);
                        }
                    }
                    EditorGUILayout.EndScrollView();
                }
                EditorGUILayout.EndVertical();
                if (GUI.Button(new Rect(position.width / 2 - 60, position.height - 35, 120, 30), "一键清除空引用"))
                {
                    ClearNowNullCommponents();
                }
            }
            EditorGUILayout.EndVertical();
        }
        private void ClearNowNullCommponents()
        {
            Debug.Log("当前拥有空脚本引用的物体个数:" + results.Count);
            for (int x = 0; x < results.Count; x++)
            {
                GameObjectUtility.RemoveMonoBehavioursWithMissingScript(results[x].Obj);
            }
            Debug.Log("移除成功");
        }
        private GUIStyle GetButtonStyle(int buttonIndex)
        {
            if (buttonIndex == selectedButtonIndex)
            {
                // Create a GUIStyle for the selected button appearance
                GUIStyle selectedButtonStyle = new GUIStyle(EditorStyles.toolbarButton);

                // Adjust the visual properties to make the border more visible
                selectedButtonStyle.normal.textColor = Color.white; // Change the text color
                selectedButtonStyle.normal.background = MakeTexture(2, 2, new Color(0.49f, 0.25f, 0.03f, 1f)); // Add a background color

                return selectedButtonStyle;
            }
            else
            {
                // Return the default button style
                return EditorStyles.miniButton;
            }
        }

        private Texture2D MakeTexture(int width, int height, Color color)
        {
            Color[] pixels = new Color[width * height];
            for (int i = 0; i < pixels.Length; i++)
            {
                pixels[i] = color;
            }

            Texture2D texture = new Texture2D(width, height);
            texture.SetPixels(pixels);
            texture.Apply();

            return texture;
        }


        private void DrawLabel(string text, GUIStyle style)
        {
            Rect rect = GUILayoutUtility.GetRect(GUIContent.none, style);
            Color32 color = new Color32(125, 64, 8, 225);
            EditorGUI.DrawRect(rect, color);
            GUI.Label(rect, text, style);
        }

        private void SerachSelectedAsset()
        {
            results.Clear();
            if (Selection.activeGameObject)
                Traverse(Selection.activeGameObject.transform);
            Debug.Log("> Total Results: " + results.Count);
        }

        public void SearchCurrentScene()
        {
            results.Clear();
            GameObject[] gos = SceneManager.GetActiveScene().GetRootGameObjects();
            foreach (GameObject go in gos) Traverse(go.transform);
            Debug.Log("> Total Results: " + results.Count);
        }

        public void SearchAssetFolder()
        {
            results.Clear();
            var allPrefabs = GetAllPrefabAddress();
            int count = 0;
            EditorUtility.DisplayProgressBar("Processing...", "Begin Job", 0);

            foreach (string prefab in allPrefabs)
            {
                UnityEngine.Object o = AssetDatabase.LoadMainAssetAtPath(prefab);

                if (o == null)
                {
                    Debug.Log("prefab " + prefab + " null?");
                    continue;
                }

                GameObject go;
                go = o as GameObject;
                if (go != null)
                {
                    EditorUtility.DisplayProgressBar("Processing...", go.name, ++count / (float)allPrefabs.Length);
                    Traverse(go.transform);


                }
            }
            Debug.Log("> Total Results: " + results.Count);
            EditorUtility.ClearProgressBar();
        }


        public string[] GetAllPrefabAddress()
        {
            string[] temp = AssetDatabase.GetAllAssetPaths();
            List<string> result = new List<string>();
            foreach (string s in temp)
            {
                if (s.Contains(".prefab")) result.Add(s);
            }
            return result.ToArray();
        }

        private void AppendComponentResult(string childPath, int index, GameObject obj)
        {
            results.Add(new Result()
            {
                address = "Missing Component " + index + " of " + childPath,
                Obj = obj,
            });
        }
        private void AppendTransformResult(string childPath, string name, GameObject obj)
        {
            results.Add(new Result()
            {
                address = "Missing Prefab for \"" + name + "\" of " + childPath,
                Obj = obj,
            });
        }
        private void Traverse(Transform transform, string path = "")
        {
            string thisPath = path + "/" + transform.name;
            Component[] components = transform.GetComponents<Component>();
            for (int i = 0; i < components.Length; i++)
            {
                if (components[i] == null)
                {
                    AppendComponentResult(thisPath, i, transform.gameObject);
                }
            }

            for (int c = 0; c < transform.childCount; c++)
            {
                Transform t = transform.GetChild(c);
                PrefabAssetType pt = PrefabUtility.GetPrefabAssetType(t.gameObject);
                if (pt == PrefabAssetType.MissingAsset)
                {
                    AppendTransformResult(path + "/" + transform.name, t.name, transform.gameObject);
                }
                else
                {
                    Traverse(t, thisPath);
                }
            }
        }
    }

    [System.Serializable]
    public class Result
    {
        public string address;
        public GameObject Obj;
    }
}

#endif

  

posted @ 2024-10-23 16:33  游戏鼻祖  阅读(3)  评论(0编辑  收藏  举报