diff --git a/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs
new file mode 100644
index 00000000..4aebead9
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs
@@ -0,0 +1,26 @@
+#if UNITY_2021_3_OR_NEWER
+using UnityEngine;
+using System;
+
+namespace NaughtyAttributes
+{
+ ///
+ /// Draws a dropdown with all types derived from the given base type
+ ///
+ public class TypeDropdownAttribute : PropertyAttribute
+ {
+ public readonly Type baseType;
+ public readonly Type defaultType;
+ public TypeDropdownAttribute(Type baseType) : this(baseType, baseType)
+ {
+
+ }
+
+ public TypeDropdownAttribute(Type baseType, Type defaultType)
+ {
+ this.baseType = baseType;
+ this.defaultType = defaultType;
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs.meta b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs.meta
new file mode 100644
index 00000000..c70fab88
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Core/DrawerAttributes/TypedDropdownAttribute.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 661f75eeab4377143834b7b532f7f49a
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs
new file mode 100644
index 00000000..1d3cfd4e
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs
@@ -0,0 +1,152 @@
+#if UNITY_2021_3_OR_NEWER
+using UnityEngine;
+using System;
+using System.Collections.Generic;
+using UnityEditor;
+
+namespace NaughtyAttributes
+{
+ public abstract class SerializedReferencePropertyDrawerBase : PropertyDrawer
+ {
+ static float lineHeight => EditorGUIUtility.singleLineHeight;
+ static float verticalSpacing => EditorGUIUtility.standardVerticalSpacing;
+ protected abstract System.Type DefaultType { get; }
+ protected abstract System.Type BaseType { get; }
+
+ System.Collections.Generic.List m_Types = new List();
+
+ bool m_Initialized = false;
+
+ ///
+ /// If you override OnGUI or GetPropertyHeight, you should call this method first
+ ///
+ protected void Init()
+ {
+ if (m_Initialized)
+ return;
+
+ CollectTypes(m_Types);
+ Initialize();
+
+ m_Initialized = true;
+ }
+
+ ///
+ /// Called after types are collected. Can be used to initialze custom fields
+ ///
+ protected virtual void Initialize()
+ {
+
+ }
+
+ ///
+ /// Called during initialization to collect types. Can be overriden to provide custom types
+ ///
+ ///
+ protected virtual void CollectTypes(List list)
+ {
+ var assemblies = System.AppDomain.CurrentDomain.GetAssemblies();
+ foreach (var assembly in assemblies)
+ {
+ foreach (var type in assembly.GetTypes())
+ {
+ if (BaseType.IsAssignableFrom(type) && !type.IsGenericType && !type.IsAbstract && type.AssemblyQualifiedName != DefaultType.AssemblyQualifiedName)
+ {
+ m_Types.Add(type);
+ }
+ }
+ }
+ }
+
+
+ public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
+ {
+ Init();
+
+ EditorGUI.BeginProperty(position, label, property);
+
+ var dropDownRect = position;
+ dropDownRect.height = lineHeight;
+ dropDownRect.x += EditorGUIUtility.labelWidth + verticalSpacing;
+ dropDownRect.width -= EditorGUIUtility.labelWidth + verticalSpacing;
+
+ DrawDropdpownContent(dropDownRect, property);
+
+ EditorGUI.PropertyField(position, property, label, true);
+ EditorGUI.EndProperty();
+ }
+
+
+ public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
+ {
+ Init();
+ return EditorGUI.GetPropertyHeight(property);
+ }
+
+ public void DrawDropdpownContent(Rect position, SerializedProperty property)
+ {
+ EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode || EditorApplication.isPaused);
+
+ var oCol = GUI.contentColor;
+ if (property.managedReferenceValue == null)
+ {
+ FillProperty(property, DefaultType);
+ }
+
+ var currentObject = property.managedReferenceValue;
+ var currentSelectorType = currentObject.GetType();
+ var currentContent = GetGUIContentForType(currentSelectorType);
+
+ var rect = position;
+
+ if (EditorGUI.DropdownButton(rect, currentContent, FocusType.Keyboard))
+ {
+ GenericMenu menu = new GenericMenu();
+ for (var i = 0; i < m_Types.Count; i++)
+ {
+ var type = m_Types[i];
+ var content = GetGUIContentForType(type);
+ bool isOn = currentContent.text == content.text;
+ menu.AddItem(content, currentContent.text == content.text, () =>
+ {
+ if (!isOn)
+ {
+ FillProperty(property, type);
+ }
+ });
+ }
+
+ menu.AddSeparator(null);
+
+ var defaultContent = GetGUIContentForType(DefaultType);
+ bool defaultIsOn = defaultContent.text == currentContent.text;
+ menu.AddItem(GetGUIContentForType(DefaultType), defaultIsOn, () =>
+ {
+ if (!defaultIsOn)
+ {
+ FillProperty(property, DefaultType);
+ }
+ });
+ menu.DropDown(rect);
+ }
+
+ GUI.contentColor = oCol;
+
+ GUIContent GetGUIContentForType(System.Type type)
+ {
+ if (type.AssemblyQualifiedName == DefaultType.AssemblyQualifiedName)
+ return new GUIContent($"{type.Name} (Default)");
+ return new GUIContent($"{type.Name}");
+ }
+ EditorGUI.EndDisabledGroup();
+ }
+
+ private static void FillProperty(SerializedProperty property, System.Type type)
+ {
+ var newAsset = Activator.CreateInstance(type);
+ property.managedReferenceValue = newAsset;
+ property.serializedObject.ApplyModifiedProperties();
+ }
+ }
+}
+#endif
\ No newline at end of file
diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs.meta b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs.meta
new file mode 100644
index 00000000..910753aa
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/SerializedReferencePropertyDrawerBase.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: ae70e28dde71d0040bb2e2ce2c031857
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs
new file mode 100644
index 00000000..43c8e725
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs
@@ -0,0 +1,15 @@
+#if UNITY_2021_3_OR_NEWER
+using System;
+using UnityEditor;
+
+namespace NaughtyAttributes
+{
+
+ [CustomPropertyDrawer(typeof(TypeDropdownAttribute))]
+ public class TypeDropdownAttributePropertyDrawer : SerializedReferencePropertyDrawerBase
+ {
+ protected override Type DefaultType => (attribute as TypeDropdownAttribute).defaultType;
+ protected override Type BaseType => (attribute as TypeDropdownAttribute).baseType;
+ }
+}
+#endif
diff --git a/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs.meta b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs.meta
new file mode 100644
index 00000000..83a41f2f
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Editor/PropertyDrawers/TypeDropdownAttributePropertyDrawer.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 18b307637a2c2d54dbd7db3c2f3a4e9c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs
new file mode 100644
index 00000000..b9bde135
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs
@@ -0,0 +1,30 @@
+#if UNITY_2021_3_OR_NEWER
+using NaughtyAttributes;
+using UnityEngine;
+
+namespace NaughtyAttributes.Test
+{
+ public class TypedDropdownTest : MonoBehaviour
+ {
+ [SerializeReference]
+ [TypeDropdown(typeof(Animal))]
+ public Animal MyPet;
+ }
+
+ [System.Serializable]
+ public class Animal
+ {
+ public string nickname = "Silly Billy";
+ }
+
+ public class Dog : Animal
+ {
+ public string Breed = "Golden Retriever";
+ }
+
+ public class Cat : Animal
+ {
+ public int lives = 9;
+ }
+}
+#endif
diff --git a/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs.meta b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs.meta
new file mode 100644
index 00000000..272e8917
--- /dev/null
+++ b/Assets/NaughtyAttributes/Scripts/Test/TypedDropdownTest.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 04bc241ae996b6b4ba2b1eb352322849
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: