Search Unity

Feature Request How to conveniently search components / scripts in hierarchy in Editor UI?

Discussion in 'Editor & General Support' started by dan-oak, Mar 23, 2022.

  1. dan-oak

    dan-oak

    Joined:
    Jul 14, 2020
    Posts:
    9
    conveniently - fuzzily, with sub-word matching, maybe even using regex patters etc.

    right now we have:
    - classical hierarchy search, which is able to only search by full case-sensitive component name,
    - new "Unity Search" package which is an advanced search with many convenient features, but no component search, like the most important thing for me and i suspect for many (?).

    if only there was any other package or script which could add a piece of UI with a component search with a useful search algorithm i would be immeasurably thankful
     
    mgear likes this.
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    I saw this yesterday:



    Disclaimer: haven't touched it yet myself.
     
  3. dan-oak

    dan-oak

    Joined:
    Jul 14, 2020
    Posts:
    9
    thank you. amazing plugin. but it's not designed for feature I'm looking for. I need a UX to operate on component inspectors in a bulk. much like the classical unity hierarchy search allows you to do, but it requires to enter the component name exactly to find it
     
  4. ramazan905tv

    ramazan905tv

    Joined:
    Jan 23, 2020
    Posts:
    1
    Possibly this gonna help you:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3. using UnityEditor;
    4. using UnityEditor.SceneManagement;
    5. using System.Collections.Generic;
    6. using System.Linq;
    7.  
    8. public class ScriptSearchWindow : EditorWindow
    9. {
    10.     private string searchQuery = "";
    11.     private List<GameObject> objectsWithScript = new List<GameObject>();
    12.     private Vector2 scrollPosition;
    13.     private Vector2 scrollPosition2;
    14.     private List<string> scriptNamesLowercase = new List<string>();
    15.     private List<string> scriptNamesOriginal = new List<string>();
    16.     private List<string> searchButton = new List<string>();
    17.     private bool SearchInAssets = false;
    18.  
    19.     [MenuItem("Window/Script Search Window")]
    20.     public static void ShowWindow()
    21.     {
    22.         var window = GetWindow<ScriptSearchWindow>("Script Search");
    23.     }
    24.  
    25.     private void OnEnable()
    26.     {
    27.         EditorSceneManager.sceneOpened += OnSceneOpened;
    28.     }
    29.  
    30.     private void OnDisable()
    31.     {
    32.         EditorSceneManager.sceneOpened -= OnSceneOpened;
    33.     }
    34.  
    35.     private void OnSceneOpened(Scene scene, OpenSceneMode mode)
    36.     {
    37.         SearchForScript();
    38.     }
    39.  
    40.     private void OnGUI()
    41.     {
    42.         GUILayout.Label("Search for Script", EditorStyles.boldLabel);
    43.         searchQuery = EditorGUILayout.TextField("Script Name:", searchQuery);
    44.  
    45.         GUIStyle resetButtonStyle = new GUIStyle(GUI.skin.button);
    46.         resetButtonStyle.normal.textColor = Color.white;
    47.         resetButtonStyle.hover.textColor = Color.white;
    48.         GUI.backgroundColor = new Color(0.8f, 0.1f, 0.1f, 1f);
    49.         if (GUILayout.Button("Reset Input", resetButtonStyle))
    50.         {
    51.             searchQuery = "";
    52.             searchButton.Clear();
    53.         }
    54.  
    55.         SearchInAssets = EditorGUILayout.Toggle("Search In Assets", SearchInAssets);
    56.  
    57.         if (searchButton.Contains(searchQuery) || string.IsNullOrEmpty(searchQuery))
    58.         {
    59.             GUI.backgroundColor = new Color(0.1f, 0.1f, 0.8f, 1f);
    60.             if (GUILayout.Button("Search"))
    61.             {
    62.                 SearchForScript();
    63.                 searchButton.Add(searchQuery);
    64.             }
    65.         }
    66.  
    67.         GUI.backgroundColor = Color.white;
    68.  
    69.         GUILayout.Label("Suggestions:");
    70.  
    71.         float scrollHeight = Mathf.Min(scriptNamesOriginal.Count * EditorGUIUtility.singleLineHeight, position.height * 0.35f);
    72.  
    73.         scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(scrollHeight));
    74.        
    75.         if (scriptNamesOriginal.Count > 0)
    76.         {
    77.             HashSet<string> uniqueSuggestions = new HashSet<string>();
    78.             List<string> suggestions = new List<string>();
    79.             foreach (string name in scriptNamesOriginal)
    80.             {
    81.                 if (name.ToLower().StartsWith(searchQuery.ToLower()) && !uniqueSuggestions.Contains(name.ToLower()))
    82.                 {
    83.                     uniqueSuggestions.Add(name.ToLower());
    84.                     suggestions.Add(name);
    85.                 }
    86.             }
    87.            
    88.             if (suggestions.Count > 0)
    89.             {
    90.                 foreach (string suggestion in suggestions)
    91.                 {
    92.                     EditorGUILayout.BeginHorizontal();
    93.                     GUIStyle suggestionButtonStyle = new GUIStyle(GUI.skin.button);
    94.                     suggestionButtonStyle.normal.textColor = Color.black;
    95.                     suggestionButtonStyle.hover.textColor = Color.black;
    96.                     GUI.backgroundColor = new Color(155f, 155f, 155f, 1f);
    97.                     if (GUILayout.Button(suggestion, suggestionButtonStyle))
    98.                     {
    99.                         searchQuery = suggestion;
    100.                         SearchForScript();
    101.                     }
    102.                     EditorGUILayout.EndHorizontal();
    103.                 }
    104.             }
    105.         }
    106.         else
    107.         {
    108.             GUILayout.Label("No Suggestions Available");
    109.         }
    110.  
    111.         GUI.backgroundColor = Color.white;
    112.        
    113.         GUILayout.EndScrollView();
    114.  
    115.         GUILayout.Label("Results:");
    116.  
    117.         scrollPosition2 = GUILayout.BeginScrollView(scrollPosition2);
    118.  
    119.         if (objectsWithScript.Count > 0)
    120.         {
    121.             foreach (GameObject obj in objectsWithScript)
    122.             {
    123.                 if (obj != null)
    124.                 {
    125.                     EditorGUILayout.BeginHorizontal();
    126.                     if (GUILayout.Button(GetObjectName(obj), "Button"))
    127.                     {
    128.                         Selection.activeGameObject = obj;
    129.                         if (PrefabUtility.IsPartOfPrefabAsset(obj))
    130.                         {
    131.                             var prefabAsset = PrefabUtility.GetCorrespondingObjectFromSource(obj);
    132.                             if (prefabAsset != null)
    133.                             {
    134.                                 AssetDatabase.OpenAsset(prefabAsset);
    135.                             }
    136.                         }
    137.                     }
    138.                     EditorGUILayout.EndHorizontal();
    139.                 }
    140.             }
    141.         }
    142.         else
    143.         {
    144.             GUILayout.Label("No Objects With Specified Script Found");
    145.         }
    146.  
    147.         GUILayout.EndScrollView();
    148.     }
    149.  
    150.     private void SearchForScript()
    151.     {
    152.         scriptNamesOriginal.Clear();
    153.         scriptNamesLowercase.Clear();
    154.         objectsWithScript.Clear();
    155.  
    156.         if (!SearchInAssets)
    157.         {
    158.             MonoBehaviour[] scripts = FindObjectsOfType<MonoBehaviour>();
    159.             foreach (MonoBehaviour script in scripts)
    160.             {
    161.                 string scriptName = script.GetType().Name;
    162.                 scriptNamesOriginal.Add(scriptName);
    163.                 scriptNamesLowercase.Add(scriptName.ToLower());
    164.                
    165.                 if (scriptName.ToLower().Contains(searchQuery.ToLower()))
    166.                 {
    167.                     objectsWithScript.Add(script.gameObject);
    168.                 }
    169.             }
    170.         }
    171.        
    172.         if (SearchInAssets)
    173.         {
    174.             MonoBehaviour[] scripts = Resources.FindObjectsOfTypeAll<MonoBehaviour>();
    175.             foreach (MonoBehaviour script in scripts)
    176.             {
    177.                 string scriptName = script.GetType().Name;
    178.                 scriptNamesOriginal.Add(scriptName);
    179.                 scriptNamesLowercase.Add(scriptName.ToLower());
    180.                
    181.                 if (scriptName.ToLower().Contains(searchQuery.ToLower()))
    182.                 {
    183.                     objectsWithScript.Add(script.gameObject);
    184.                 }
    185.             }
    186.         }
    187.  
    188.         objectsWithScript = objectsWithScript.Distinct().ToList();
    189.     }
    190.  
    191.     private string GetObjectName(GameObject obj)
    192.     {
    193.         if (PrefabUtility.IsPartOfPrefabAsset(obj))
    194.         {
    195.             return "(Prefab) " + obj.name;
    196.         }
    197.         else
    198.         {
    199.             return obj.name;
    200.         }
    201.     }
    202. }
    203.