Attribute To Add Button To Class

I’ve looked into this before and it seems somewhere between difficult and impossible, but it would be nice to have a shorthand for “Assign this method to a button in the inspector”. Something like:

[InspectorButton("Foo")]
public void Foo{
  //Do something
}

Does else think this would be useful? I know that it is pretty simple to do this with a custom editor, but it would still be nice to have a shorthand for when you’d like to run a quick test.

What a great idea!

Hey, lookie that, someone already did it… here you go! GitHub - madsbangh/EasyButtons: Add buttons to your inspector in Unity super easily with this simple attribute

There’s also a much more comprehensive package on the Asset Store called AdvancedInspector, which is also quite a cool package to play with. I’ve had that going in a few projects.

3 Likes

Heck yeah! This is awesome! I need to go through and figure out how they did it, this is an awesome chance to learn more about C# attributes. Thank you for pointing me to this. Combined with a ReadOnly attribute this could make rapid testing and debugging even easier.

1 Like

Here’s another option I just wrote up if you want something simple and contained in just one file.

using UnityEngine;

#if UNITY_EDITOR
using UnityEditor;
#endif

#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(ButtonAttribute))]
public class ButtonDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        string methodName = (attribute as ButtonAttribute).MethodName;
        Object target = property.serializedObject.targetObject;
        System.Type type = target.GetType();
        System.Reflection.MethodInfo method = type.GetMethod(methodName);
        if (method == null)
        {
            GUI.Label(position, "Method could not be found. Is it public?");
            return;
        }
        if (method.GetParameters().Length > 0)
        {
            GUI.Label(position, "Method cannot have parameters.");
            return;
        }
        if (GUI.Button(position, method.Name))
        {
            method.Invoke(target, null);
        }
    }
}
#endif

public class ButtonAttribute : PropertyAttribute
{
    public string MethodName { get; }
    public ButtonAttribute(string methodName)
    {
        MethodName = methodName;
    }
}

And then you use it like this:

using UnityEngine;

public class TestBehaviour : MonoBehaviour
{
    [Button(nameof(RunTest))]
    public bool buttonField;

    public void RunTest()
    {
        Debug.Log("test ran");
    }
}
6 Likes

If a context menu is good enough for your use case, then you can use the built in ContextMenu attribute on your debug method

1 Like