I would like a method to be called every time I select a value from a dropdown in the Inspector. Is this possible?
Code sample:
public class Animal : MonoBehaviour
{
public enum AnimalType
{
Dog, Cat, Hamster, Bunny,
}
[SerializeField] private AnimalType animalType;
// TODO: Call this function every time I select a value
// from the enum dropdown in the Inspector.
private void OnAnimalSelected() { }
}
Think you might be looking for this.
2 Likes
Thanks, but that one gets called more often than I need it to be. It also gets called very early, seemingly before Awake, and because of that I cannot access components in it that I have set with GetComponent in Awake.
The answer is via a custom inspector.
1 Like
You can achieve this with a custom property attribute and property drawer.
Something like this:
[AttributeUsage(AttributeTargets.Field), Conditional("UNITY_EDITOR")]
public sealed class OnValueChangedAttribute : PropertyAttribute
{
public string MethodName { get; }
public OnValueChangedAttribute(string methodName) => MethodName = methodName;
}
[CustomPropertyDrawer(typeof(OnValueChangedAttribute))]
public class OnValueChangedAttributeDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
var result = new PropertyField(property);
result.RegisterValueChangeCallback(OnValueChanged);
return result;
static void OnValueChanged(SerializedPropertyChangeEvent @event)
{
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var serializedProperty = @event.changedProperty;
var targets = serializedProperty.serializedObject.targetObjects;
var type = targets.First().GetType();
var field = type.GetField(serializedProperty.name, flags);
var attribute = field.GetCustomAttributes(typeof(OnValueChangedAttribute), false).First() as OnValueChangedAttribute;
var method = type.GetMethod(attribute.MethodName, flags);
Undo.RecordObjects(targets, "On Value Changed");
foreach(var target in targets)
{
var parameters = method.GetParameters();
switch(parameters.Length)
{
case 0:
method.Invoke(target, null);
break;
case 1 when parameters[0].ParameterType is Type parameterType:
if(parameterType == typeof(SerializedProperty))
{
method.Invoke(target, new object[] { serializedProperty });
}
else
{
method.Invoke(target, new object[] { field.GetValue(target) });
}
break;
}
}
serializedProperty.serializedObject.Update();
}
}
}
And usage:
[OnValueChanged(nameof(OnValueChanged))]
private float value;
private void OnValueChanged(float value)
{
Debug.Log("Value changed to: " + value);
}
1 Like