[Solved] Can I add options to the Component Context Menu?

Components on a GameObject have a little “gear” wheel icon like this:

https://s29.postimg.org/wb6ib1eon/Capture.png

Is it possible to add new functions to this menu?

Yes, its possible. Look into the MenuItem attribute in the UnityEditor namespace.

// Add a menu item called "Double Mass" to a Rigidbody's context menu.
[MenuItem ("CONTEXT/Rigidbody/Double Mass")]
static void DoubleMass (MenuCommand command) {
    Rigidbody body = (Rigidbody)command.context;
    body.mass = body.mass * 2;
    Debug.Log ("Doubled Rigidbody's Mass to " + body.mass + " from Context Menu.");
}

CONTEXT/Rigidbody is what makes it show up only on context menu for a Rigidbody component. Without “CONTEXT” it would appear as a menu item at the top of the editor

Though the example on the page has it in a MonoBehaviour script you would probably want it in an Editor script and in the Editor folder. since the attribute belongs in the UnityEditor namespace it would cause issues otherwise when you try to build. so it doesn’t make much sense to write it in a MonoBehaviour, at least without a preprocessor.

11 Likes

Thanks that’s cool but in the MenuItem constructor the class namespace cannot be specified. I have a component with the same name as a Unity component so this adds it for both. Anyway around this?

then just include the namespace

[UnityEditor.MenuItem(“CONTEXT/Elemental/Do Stuff”)]

learn to put your classes inside namespaces to avoid such name conflicts

My class is inside a namespace. This is how I tried using it:

[MenuItem (“CONTEXT/MyNamespace.Rigidbody/Double Mass”)]

But doesn’t work.

1 Like

Oh, no I don’t think you can selectively show it on one component and not the other, but you can have the function check if the command.context is your component and not Unity’s

MyNamespace.RigidBody rb = command.context as MyNamespace.RigidBody;

if(rb == null) //if the cast fails or if RB really was null then don't do anything
    return;

//else do stuff for MyNamespace.RigidBody

then again it begs the question why would you use the same name as a builtIn unity component. I could see a risk where the user adds the wrong component because of this similar name. having the Custom Context menu item show up on both components is just the price of this design decision.

3 Likes

Is there a way to target all monobehaviours like so? I’d love to add some functionally static classes to quickly clear up scripts through the gear icon.

However I just can’t seem to target all monobehaviours.

What I am looking for is something like “edit script” when you right-click the gear icon.

Cheers

1 Like

For posterity: @zero_equals_zero

You can use these:

[MenuItem("CONTEXT/Object/YOUR_COMMAND")]

or

[MenuItem("CONTEXT/Component/YOUR_COMMAND")]
10 Likes

Now you can use (sample):

#if UNITY_EDITOR
        private const string menuCaption1 = "Menu item 1";
        private const string menuCaption2 = "Menu item 2";

        // OPTIONAL VALIDATING
        // [ContextMenu(menuCaption1, true)]
        // [ContextMenu(menuCaption2, true)]
        // public bool ApplicationIsPlayingValidate() => Application.isPlaying;

        [ContextMenu(menuCaption1, false, 10000001)]
        public void RunMenuItem1() { /*...*/ }

        [ContextMenu(menuCaption2, false, 10000002)]
        public void RunMenuItem2() { /*...*/ };
#endif
2 Likes