Skip to content

Instantly share code, notes, and snippets.

@Cyanilux
Last active December 27, 2023 17:25
Show Gist options
  • Save Cyanilux/7191652386494d459b3204c8ad40d7b1 to your computer and use it in GitHub Desktop.
Save Cyanilux/7191652386494d459b3204c8ad40d7b1 to your computer and use it in GitHub Desktop.
PropertyAttribute/Drawer used to auto-filter ObjectPicker window (showing assets / scene references) by name - Unity, IMGUI
// Example usage in some other script
[FilterObjectPicker("Projectile")]
public GameObject projectilePrefab;
// When clicking object field in inspector, would only see gameobjects with "Projectile" in name.
// Can remove filter text at top of object picker to see all gameobjects again.
// To allow scene references, add second param as true. e.g. :
[FilterObjectPicker("Test", true)]
public GameObject someSceneObject;
// (These scripts were created/tested in Unity 2022.2)
using UnityEngine;
public class FilterObjectPickerAttribute : PropertyAttribute {
public string filter;
public bool allowSceneObjects;
public FilterObjectPickerAttribute(string filter, bool allowSceneObjects = false){
this.filter = filter;
this.allowSceneObjects = allowSceneObjects;
}
}
// (Put under Editor folder)
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(FilterObjectPickerAttribute))]
public class FilterObjectPickerPropertyDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
EditorGUI.BeginProperty(position, label, property);
int controlID = GUIUtility.GetControlID(FocusType.Passive);
Event e = Event.current;
if (e.type == EventType.MouseUp && position.Contains(e.mousePosition)) {
e.Use();
System.Type type = fieldInfo.FieldType;
if (type.IsArray){ // e.g. GameObject[]
type = type.GetElementType();
}else if (type.IsGenericType && type.GenericTypeArguments.Length > 0){ // e.g. List<GameObject>
type = type.GenericTypeArguments[0];
}
// some common types, feel free to add more if needed.
// not sure if there's a better way to handle this
if (type == typeof(GameObject)) {
ShowObjectPicker<GameObject>(property.objectReferenceValue, controlID);
} else if (type == typeof(Mesh)) {
ShowObjectPicker<Mesh>(property.objectReferenceValue, controlID);
} else if (type == typeof(Material)) {
ShowObjectPicker<Material>(property.objectReferenceValue, controlID);
} else if (type == typeof(Texture2D)) {
ShowObjectPicker<Texture2D>(property.objectReferenceValue, controlID);
} else if (type == typeof(Sprite)) {
ShowObjectPicker<Sprite>(property.objectReferenceValue, controlID);
} else if (type.BaseType == typeof(ScriptableObject)) {
// will show all scriptable object types, but better than showing other assets
ShowObjectPicker<ScriptableObject>(property.objectReferenceValue, controlID);
} else {
// a different type, have to just show all assets... :\
ShowObjectPicker<Object>(property.objectReferenceValue, controlID);
}
} else if (e.type == EventType.ExecuteCommand && e.commandName == "ObjectSelectorUpdated" && controlID == EditorGUIUtility.GetObjectPickerControlID()) {
e.Use();
property.objectReferenceValue = EditorGUIUtility.GetObjectPickerObject();
}
EditorGUI.PropertyField(position, property, label);
EditorGUI.EndProperty();
}
public void ShowObjectPicker<T>(Object obj, int controlID) where T : Object {
var att = (FilterObjectPickerAttribute)attribute;
EditorGUIUtility.ShowObjectPicker<T>(obj, att.allowSceneObjects, att.filter, controlID);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment