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
1 Like
I saw this yesterday:
Disclaimer: haven’t touched it yet myself.
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
Possibly this gonna help you:
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEditor;
using UnityEditor.SceneManagement;
using System.Collections.Generic;
using System.Linq;
public class ScriptSearchWindow : EditorWindow
{
private string searchQuery = "";
private List<GameObject> objectsWithScript = new List<GameObject>();
private Vector2 scrollPosition;
private Vector2 scrollPosition2;
private List<string> scriptNamesLowercase = new List<string>();
private List<string> scriptNamesOriginal = new List<string>();
private List<string> searchButton = new List<string>();
private bool SearchInAssets = false;
[MenuItem("Window/Script Search Window")]
public static void ShowWindow()
{
var window = GetWindow<ScriptSearchWindow>("Script Search");
}
private void OnEnable()
{
EditorSceneManager.sceneOpened += OnSceneOpened;
}
private void OnDisable()
{
EditorSceneManager.sceneOpened -= OnSceneOpened;
}
private void OnSceneOpened(Scene scene, OpenSceneMode mode)
{
SearchForScript();
}
private void OnGUI()
{
GUILayout.Label("Search for Script", EditorStyles.boldLabel);
searchQuery = EditorGUILayout.TextField("Script Name:", searchQuery);
GUIStyle resetButtonStyle = new GUIStyle(GUI.skin.button);
resetButtonStyle.normal.textColor = Color.white;
resetButtonStyle.hover.textColor = Color.white;
GUI.backgroundColor = new Color(0.8f, 0.1f, 0.1f, 1f);
if (GUILayout.Button("Reset Input", resetButtonStyle))
{
searchQuery = "";
searchButton.Clear();
}
SearchInAssets = EditorGUILayout.Toggle("Search In Assets", SearchInAssets);
if (searchButton.Contains(searchQuery) || string.IsNullOrEmpty(searchQuery))
{
GUI.backgroundColor = new Color(0.1f, 0.1f, 0.8f, 1f);
if (GUILayout.Button("Search"))
{
SearchForScript();
searchButton.Add(searchQuery);
}
}
GUI.backgroundColor = Color.white;
GUILayout.Label("Suggestions:");
float scrollHeight = Mathf.Min(scriptNamesOriginal.Count * EditorGUIUtility.singleLineHeight, position.height * 0.35f);
scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(scrollHeight));
if (scriptNamesOriginal.Count > 0)
{
HashSet<string> uniqueSuggestions = new HashSet<string>();
List<string> suggestions = new List<string>();
foreach (string name in scriptNamesOriginal)
{
if (name.ToLower().StartsWith(searchQuery.ToLower()) && !uniqueSuggestions.Contains(name.ToLower()))
{
uniqueSuggestions.Add(name.ToLower());
suggestions.Add(name);
}
}
if (suggestions.Count > 0)
{
foreach (string suggestion in suggestions)
{
EditorGUILayout.BeginHorizontal();
GUIStyle suggestionButtonStyle = new GUIStyle(GUI.skin.button);
suggestionButtonStyle.normal.textColor = Color.black;
suggestionButtonStyle.hover.textColor = Color.black;
GUI.backgroundColor = new Color(155f, 155f, 155f, 1f);
if (GUILayout.Button(suggestion, suggestionButtonStyle))
{
searchQuery = suggestion;
SearchForScript();
}
EditorGUILayout.EndHorizontal();
}
}
}
else
{
GUILayout.Label("No Suggestions Available");
}
GUI.backgroundColor = Color.white;
GUILayout.EndScrollView();
GUILayout.Label("Results:");
scrollPosition2 = GUILayout.BeginScrollView(scrollPosition2);
if (objectsWithScript.Count > 0)
{
foreach (GameObject obj in objectsWithScript)
{
if (obj != null)
{
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button(GetObjectName(obj), "Button"))
{
Selection.activeGameObject = obj;
if (PrefabUtility.IsPartOfPrefabAsset(obj))
{
var prefabAsset = PrefabUtility.GetCorrespondingObjectFromSource(obj);
if (prefabAsset != null)
{
AssetDatabase.OpenAsset(prefabAsset);
}
}
}
EditorGUILayout.EndHorizontal();
}
}
}
else
{
GUILayout.Label("No Objects With Specified Script Found");
}
GUILayout.EndScrollView();
}
private void SearchForScript()
{
scriptNamesOriginal.Clear();
scriptNamesLowercase.Clear();
objectsWithScript.Clear();
if (!SearchInAssets)
{
MonoBehaviour[] scripts = FindObjectsOfType<MonoBehaviour>();
foreach (MonoBehaviour script in scripts)
{
string scriptName = script.GetType().Name;
scriptNamesOriginal.Add(scriptName);
scriptNamesLowercase.Add(scriptName.ToLower());
if (scriptName.ToLower().Contains(searchQuery.ToLower()))
{
objectsWithScript.Add(script.gameObject);
}
}
}
if (SearchInAssets)
{
MonoBehaviour[] scripts = Resources.FindObjectsOfTypeAll<MonoBehaviour>();
foreach (MonoBehaviour script in scripts)
{
string scriptName = script.GetType().Name;
scriptNamesOriginal.Add(scriptName);
scriptNamesLowercase.Add(scriptName.ToLower());
if (scriptName.ToLower().Contains(searchQuery.ToLower()))
{
objectsWithScript.Add(script.gameObject);
}
}
}
objectsWithScript = objectsWithScript.Distinct().ToList();
}
private string GetObjectName(GameObject obj)
{
if (PrefabUtility.IsPartOfPrefabAsset(obj))
{
return "(Prefab) " + obj.name;
}
else
{
return obj.name;
}
}
}