Unity Editor: Menu Items

Unity Editor: Menu Items

When making a tool, you may want the user to be able to press a button in the navigation menu in Unity. Whether that be to open a editor window, perform a function or clear for player prefs. Making menu items can be very useful for your tools. This post will go through how to set them up and any quirks I found when making my own tools.

Basic setup up

To setup a menu item you need to apply the attribute [MenuItem] to any static editor method. The method doesn’t need to be public for it to work with this attribute. The method does need to be a method either in the editor space such as an editor folder or in an #if define with UNITY_EDITOR, otherwise you won’t be able to make a build of your project. An example below:

This produces the following once compiled:

using UnityEditor;            // Menu item is in the editor namespace.

public static class MyEditorClass 
{
    [MenuItem("My Custom Menu/My Menu Item")]
    private static void OnMenuItemPressed()
    {
        
    }
}

Attribute settings

The attribute requires you to give it a name/path to use. It can go under existing tabs in the navigation menu if you want it to. Just use that tab name as the root and it should go under that tab when comiled. You can also set the order for the item to draw at as an optional override, which can be finiky to get working. Some general tips for setting it up:

  • The menu path cannot be a single item, it much have a root path to be under:
// Valid - Has a parent path.
[MenuItem("My Custom Menu/My Menu Item")]
private static void OnMenuItemPressed()
{
    
}

// Invalid - Will throw an error in the editor.
[MenuItem("My Menu Item")]
private static void OnMenuItemPressed()
{
    
}

Setting the priority can be a pain, sometimes you may need to reload the project for it to take effect while other times it’ll update just fine when compiling. You can get the dividers to show if your priority is greater than 10 from the last in the menu path.

This example produced the following:

using UnityEditor;            // Menu item is in the editor namespace.

public static class MyEditorClass 
{
    [MenuItem("My Custom Menu/My Menu Item", priority = 1)]
    private static void OnMenuItemPressed()
    {
        
    }
    
    
    [MenuItem("My Custom Menu/My Menu Item 2", priority = 13)]
    private static void OnMenuItemPressedAsWell()
    {
        
    }
    
    
    [MenuItem("My Custom Menu/My Menu Item 3", priority = 2)]
    private static void OnMenuItemPressedAlso()
    {
        
    }
    
    
    [MenuItem("My Custom Menu/My Menu Item 4", priority = 100)]
    private static void OnMenuItemPressedAgain()
    {
        
    }
}

If you want, you can also add custom shortcuts to your frequently used menu items. Add them after your I’d be careful with these and only use them when you know its going to be used often as you’ll like hit a conflict with another tool in larger projects.

  • % or ^ = CTRL
  • # = SHIFT
  • & = ALT
  • _ = No prefix buttons

You can combine these together to to make sequences like CTRL – ATL etc. If you just want say “g” to run it without a pre-req button using the _ beforehand to do that.

using UnityEditor;            // Menu item is in the editor namespace.

public static class MyEditorClass 
{
    [MenuItem("My Custom Menu/My Menu Item", priority = 1)]
    private static void OnMenuItemPressed()
    {
    }
    
    
    // Will also run on the shortcut: CTRL-G
    [MenuItem("My Custom Menu/My Menu Item/My Sub-Menu Item %g")]
    private static void OnMenuItemPressedAsWell()
    {
        // Will appear in a sub menu...
    }
}

You can also sub-menu items by making the path longer using a dash to seperate the menu items. This can go on for a long as you like, but I wouldn’t go too mad if I were you. The example here produces:

using UnityEditor;            // Menu item is in the editor namespace.

public static class MyEditorClass 
{
    [MenuItem("My Custom Menu/My Menu Item", priority = 1)]
    private static void OnMenuItemPressed()
    {
    }
    
    
    [MenuItem("My Custom Menu/My Menu Item/My Sub-Menu Item")]
    private static void OnMenuItemPressedAsWell()
    {
        // Will appear in a sub menu...
    }
}
  • There is also an additional override field for a validate function. Though I have yet to find a use-case for this personally in my tools so far. But if you define a menu item method as a validation function, you can do checks before running a menu item like so:
using UnityEditor;            // Menu item is in the editor namespace.

public static class MyEditorClass 
{
    [MenuItem("My Custom Menu/My Menu Item", priority = 1)]
    private static void OnMenuItemPressed()
    {
        // Logic to run only if the check was true...
    }
    
    
    // Note the menu item path is the same as the actual logic method!
    [MenuItem("My Custom Menu/My Menu Item", true)]
    private static bool ValidateOnMenuItemPressed()
    {
        // Do a check here or something...
        return true;
    }
}

Further reading

Unity docs for menu items: https://docs.unity3d.com/ScriptReference/MenuItem.html

May 2023 Update

May 2023 Update

Its been about a month since my last update post. So its about time I updated you all on developments over the last few weeks. Starting on from the last post withā€¦

Save Manager 2.x

As you will have seen by now, the new Save Manager has been released! So far so good. There hasnā€™t been any major problems from what I can tell so far as Iā€™ve been using it in my personal projects to handle save data there. I have made a few minor updates to the asset since launch to fix some minor issues, most of which didnā€™t actually break anything. But they would throw some console messages which could confuse users.

As of writing the asset is on version 2.0.4. Some improvements were also made such as an option to hide the save keys for induvidual save values, reducing the clutter on the save editor. As well as a fix to allow the demo logic to be totally removed from the asset without any errors occurring. Before there was a direct type reference in the save editor window logic to determine if it would show the demo save object data. This has been changed to a type string comparison to fix the issue.

There are plans for some further QOL & feature updates in the future, such as save slots & a better API to allow for custom encryption options. These will be worked on once I get some time to look into it.

You can get the new Save Manager here:

Whatā€™s Next?

It wonā€™t be a surprise to those who read the year in review for 2022 or been following on the socials, that the next main project is the Audio Manager update. Like the Save Manager, it is getting a rewrite in the backend. This is mostly due to the 2.xā€™s setup not being easy to update for the new features & setup I want to implement next.

The current plan is to have this update out by the end of August. Similar to the deadline of April I gave myself for the Save Manager. So 4 months to fully develop & release the asset update. Now this isnā€™t a flexible deadline and may change if its just not ready in time. Likewise, if it is ready earlier than planned then itā€™ll release early. Iā€™ll post updates with progress and a release date nearer the time as well.

Functionally the Audio Manager wonā€™t change much for the end user, but behind the scenes a lot of work is going to be done to make it just a lot easier to use. Some of these include:

  • Automatic Library Management
    • Youā€™ll no longer need to manually scan for clips via and inspector or anything. When you import audio, the manager will find a process it automatically for you. There will be an option to manually scan still if needed. This also makes the setup simpler which is a bonus!
  • Static Audio Manager
    • While having the option of an instanced manager can be handy, 99% of the time it wonā€™t be needed. So in 3.x the whole system is static. So no need to use ā€œinstanceā€ when calling for audio to play.
  • New Library Window
    • While 2.x had a basic library editor for each audio manager file. 3.x will have a proper editor window with all the settings you need. You can even change the key of the clip! It also has a search option to search through the entire library and select any clip with ease.
  • Helper Structs
    • A new system for 3.x that will make typoā€™s a thing of the past. Instead of calling ā€œAudioManager.Play(ā€MyClipā€)ā€ youā€™ll be able to call a helper class called ā€œClipā€ to let you select the clip with intellisense. So that same call becomes ā€œAudioManager.Play(Clip.MyClip)ā€. There are other helper structs for groups and mixers as well.
  • Grouping
    • Speaking of groups, youā€™ll be able to group clips together in the audio library and call for a clip from that group to play. Handle if you have a lot of variations or want to play a clip from a range of options.
  • Dynamic Start Time
    • An experimental feature that tries to guess when the clip actually starts playing audio at a loud enough volume. Then sets the clip to start just before then instead of at 0. You can toggle the feature on/off globally, per clip in the library or via the method call itself. Youā€™ll also be able to adjust the settings to get a better guess time in the audio library.

Currently it is still early days and some of these features may change a tad. One thing I mentioned in my last post was a method chaining API for calling audio to play. Sadly Iā€™ve had to scrap this, but Iā€™m still working to make the API better as a whole. The amount of methods in 2.x was a bit much, so Iā€™ll be consolidating and using a better base method to avoid issues with call parameters.

Overall the idea is to build upon 2.xā€™s success with new QOL features & automation where possible. The music side of things is in the air at the moment, as Iā€™ve always struggled with a good generic solution for it. But if all goes well Iā€™ll have a little time to research something for that. Iā€™ve already had a few suggestions for it which I have noted down.

Other Projects

As mentioned in my last post. Iā€™m also working on a personal project as well to kind of replicate P5ā€™s turn based combat into a small demo game of just that mechanic. This is entirely for portfolioā€™s sake as itā€™ll make for a strong project that I can talk about in detail with a lot of systems. It also makes a good testbed for these asset updates. Save Manager 2.x was tested in the project to make sure it was all working before release and Audio Manager 3.x will get the same testing as and when its at that stage. That project is going well at the moment and I juggle my time between both it and the active Carter Games project to keep it fresh.

Organisation

This week I spent an evening or two organising the mess that was the Carter Games Notion. I legit didnā€™t use it as it was such a mess to find anything. With the new setup I will be using it a lot more. While its not something you see much, it does help to have a goal in mind and to write down tasks so you know where youā€™re at and what is left to do. Below is the Audio Manager task board for example:

The new structure has goals as ā€œEpicsā€ which then have ā€œTasksā€ to complete. Epics & Tasks are linked to ā€œProjectsā€ which hold branding, links & anything else specific to that project on them. Even this blog post is been written in Notion under the new Marketing section xD

Website & Socials

A little heads up that I plan to change up the discord a tad at sometime. Mostly just removing bloat channels and making super simple. Its not used that much anyways and I want to have a place for update notifications for assets/games as well as the general news/announcements section.

Iā€™ve also slowly been updating the documentation for all the assets to the new docs setup on the website. Iā€™m mostly there at this point with Leaderboard Manager being the only asset to fully update. Iā€™m hoping to have that all done at some point xD

So yea, thatā€™s about it for this post. Long story short; a lot going on behind the scenes xD Iā€™ll post another update around the end of June with progress if there is enough to share.

Whats coming in Save Manager 2.x?

Whats coming in Save Manager 2.x?

Currently the save manager is the asset with the longest time since its last update & with the most progress on its update. As this is the case I felt like updating you all with what has changed between the old and new versions and how it’s progressing so far.

The bad with the old setup

1.x while stable it has a lot of flaws both in workflow and how adaptable it is to different projects. The setup only allowed for 1 save data class which could easily get bloated and was often a slightly inconvient setup for non serializable types such as vectors. The setup also had no way of editing the save in the editor which is inconvient when debugging issues with projects.

What is the new version offering?

The new version offers a much more modular setup which addresses all of the above and more. This currently includes:


Save Objects & Values


  • Save objects holding a collection of values that can be defined as needed.
  • Can save Vectors & Colors as their normal values. No need for SaveVector2 etc anymore.
  • Can store as many objects as needed.
  • Tool like in 1.x to help make save objects.
  • Easily make variants of data in the save with different save keys.

Save Editor


  • Ability to edit all save data in a window.
  • Changes in values apply to game save when changed.
  • View/hide each save object & save value.
  • Easy reset for objects & values.

Save Profiles


  • Ability to save a copy of the current save data setup in the editor and load back to it when needed.
  • Profiles can also be edited in the normal Unity editor if needed.
  • Changing data structure will reset values in profiles, not ideal but the feature is intended for debugging mostly and struture changes can be worked around.

Saving Icon

The ability to show an icon on a canvas when the game is saving for a defined amoount of time. Handy if you want to let the user know the game is saving and that they should not close the game while it is active. Currently is still a work in progress but the first version is working as of writing.

Faster saving and loading


  • Data stored in dictionaries for better performance.
  • Saving and loading process has additional catches to avoid issues.

What is still to-do?


As of writing there is still a fair amount of work to do on the asset before it reaches a testable version. This includes a load of bug fixes to the current setup & a few features I’ve yet to implement which include:

  • Save Encryption
    • A way to let the user encrypt the save data should they wish to for extra security.
  • Path Remapping
    • Support for the user to remap the save path for the save data outside of the project as well as any editor paths for generates files from the asset such as settings assets & save profiles.
  • Additional Collection Types
    • Support for the normal Lists/Arrays as well as other variants and dictionaries.
  • WebGL Support?
    • A planned feature that 1.x didn’t support. My hope is to find a solution to let this new setup work on Web builds. But I do need to do some more research on this to be sure that it’ll work.
  • Documentation & Tutorial Media
    • The big bad of any asset, the docs. Always a slow process. For 2.x I plan to work find a good solution for the docs to be hosted on that I like, It’ll follow a similar structure to the Multi Scene docs I wrote last year though. With some video tutorials going over the basics of how to use the asset to hopefully help new users with commonly asked questions.

ETA?

I don’t have a firm date for release yet as I need to finish the code first, but I imagine that it’ll be ready by around April at the latest. I’ll post a more exact date when I have one but for now that is the best I can give you.