Last active
January 25, 2025 18:18
-
-
Save zombience/de7b367e253f8635f2a9be0035d7d947 to your computer and use it in GitHub Desktop.
Unity3D: Search for any Components on a given game object, present as selectable object fields
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections.Generic; | |
public class ComponentGrabber : MonoBehaviour | |
{ | |
[SerializeField, HideInInspector] | |
string searchTerm, filter; | |
[HideInInspector] | |
public List<Component> curSelection = new List<Component>(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEditor; | |
using IEDLabs.Utilities; | |
using IEDLabs.EditorUtilities; | |
[CustomEditor(typeof(ComponentGrabber))] | |
public class ComponentGrabberEditor : InspectorMonoBase<ComponentGrabber> | |
{ | |
Component[] components; | |
SerializedProperty searchTerm; | |
SerializedProperty filter; | |
protected override void OnEnable() | |
{ | |
base.OnEnable(); | |
searchTerm = serializedObject.FindProperty("searchTerm"); | |
filter = serializedObject.FindProperty("filter"); | |
showDefaultInspector = false; | |
} | |
public override void OnInspectorGUI() | |
{ | |
base.OnInspectorGUI(); | |
GUILayout.BeginVertical(style); | |
style.SectionLabel("search component types", 10, Color.magenta * .45f); | |
searchTerm.stringValue = GUILayout.TextArea(searchTerm.stringValue, GUILayout.ExpandWidth(true)); | |
if (!string.IsNullOrEmpty(searchTerm.stringValue)) | |
{ | |
foreach (var item in Utilities.FindTypesContaining(searchTerm.stringValue)) | |
{ | |
either.Button(string.Format("find components of type: {0}", item.Name), () => | |
{ | |
components = obj.GetComponentsInChildren(item); | |
}); | |
} | |
} | |
GUILayout.EndVertical(); | |
Space(30); | |
if (components != null && components.Length > 0) | |
{ | |
GUILayout.BeginVertical(style); | |
style.SectionLabel("filter found types", 10, Color.cyan * .45f); | |
GUI.backgroundColor = Color.white; | |
filter.stringValue = GUILayout.TextArea(filter.stringValue, GUILayout.ExpandWidth(true)); | |
GUI.backgroundColor = bg; | |
if(!string.IsNullOrEmpty(filter.stringValue)) | |
{ | |
components = components.Where(c => c.name.ToLower().Contains(filter.stringValue.ToLower())).ToArray(); | |
} | |
either.Button("clear filter", () => | |
{ | |
filter.stringValue = string.Empty; | |
}); | |
Space(30); | |
style.SectionLabel("components: ", 20, Color.cyan * .45f); | |
either.Button("select all", () => | |
{ | |
Selection.objects = components.Select(c => c.gameObject).ToArray(); | |
}); | |
GUILayout.BeginHorizontal(); | |
either.Button("enable all", () => | |
{ | |
for (int i = 0; i < components.Length; i++) | |
{ | |
MonoBehaviour mb = components[i] as MonoBehaviour; | |
if (mb != null) mb.enabled = true; | |
} | |
}); | |
either.Button("disable all", () => | |
{ | |
for (int i = 0; i < components.Length; i++) | |
{ | |
MonoBehaviour mb = components[i] as MonoBehaviour; | |
if (mb != null) mb.enabled = false; | |
} | |
}); | |
either.Button("destroy all", () => | |
{ | |
for (int i = 0; i < components.Length; i++) | |
{ | |
GameObject.DestroyImmediate(components[i]); | |
} | |
components = new Component[0]; | |
}); | |
GUILayout.EndHorizontal(); | |
for (int i = 0; i < components.Length; i++) | |
{ | |
Component c = components[i]; | |
GUILayout.BeginHorizontal(); | |
if(!obj.curSelection.Contains(c)) | |
{ | |
either.Button("+", () => | |
{ | |
obj.curSelection.Add(c); | |
serializedObject.Update(); | |
serializedObject.ApplyModifiedProperties(); | |
}); | |
} | |
EditorGUILayout.ObjectField(components[i], components[i].GetType(), false); | |
GUILayout.EndHorizontal(); | |
} | |
GUILayout.EndVertical(); | |
} | |
if(obj.curSelection.Count == 0) | |
{ | |
serializedObject.ApplyModifiedProperties(); | |
return; | |
} | |
Space(30); | |
GUILayout.BeginVertical(style); | |
style.SectionLabel("current selection:", 20, Color.magenta * .55f); | |
GUILayout.BeginHorizontal(); | |
editor.Button("clear selection", () => | |
{ | |
obj.curSelection.Clear(); | |
serializedObject.Update(); | |
serializedObject.ApplyModifiedProperties(); | |
}); | |
editor.Button("select objects", () => | |
{ | |
if (obj.curSelection != null && obj.curSelection.Count > 0) | |
{ | |
Selection.objects = obj.curSelection.Select(c => c.gameObject).ToArray(); | |
} | |
}); | |
GUILayout.EndHorizontal(); | |
Space(10); | |
GUILayout.BeginHorizontal(); | |
either.Button("enable selected", () => | |
{ | |
for (int i = 0; i < obj.curSelection.Count; i++) | |
{ | |
MonoBehaviour mb = obj.curSelection[i] as MonoBehaviour; | |
if (mb != null) mb.enabled = true; | |
} | |
}); | |
either.Button("disable selected", () => | |
{ | |
for (int i = 0; i < obj.curSelection.Count; i++) | |
{ | |
MonoBehaviour mb = obj.curSelection[i] as MonoBehaviour; | |
if (mb != null) mb.enabled = false; | |
} | |
}); | |
either.Button("destroy selected", () => | |
{ | |
for (int i = 0; i < obj.curSelection.Count; i++) | |
{ | |
GameObject.DestroyImmediate(obj.curSelection[i]); | |
} | |
obj.curSelection.Clear(); | |
serializedObject.Update(); | |
serializedObject.ApplyModifiedProperties(); | |
}); | |
GUILayout.EndHorizontal(); | |
Space(10); | |
for (int i = 0; i < obj.curSelection.Count; i++) | |
{ | |
Component c = obj.curSelection[i]; | |
GUILayout.BeginHorizontal(); | |
either.Button("-", () => | |
{ | |
obj.curSelection.Remove(c); | |
serializedObject.Update(); | |
serializedObject.ApplyModifiedProperties(); | |
}); | |
EditorGUILayout.ObjectField(c, typeof(Component), true); | |
GUILayout.EndHorizontal(); | |
} | |
GUILayout.EndVertical(); | |
serializedObject.ApplyModifiedProperties(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ComponentGrabber
ComponentGrabber.cs must be put on a GameObject
ComponentGrabber.Inspector.cs must be placed in a folder named Editor
begin typing search term to filter results, click on desired component to search child hierarchy for components
WHY
When dealing with rigged character hierarchies sometimes there are components deeply nested that are a pain to attempt to locate.
This makes it easy.