Skip to content

Getting Started with Custom Editors in Unity

Making a custom editor in Unity is easier than you would expect.

Select your Custom Editor Type

First, you’ll need to decide what type of custom editor your making. To have custom fields or field modifiers use PropertyDrawers, to have custom editors for a script use Editor, and to have an entire custom editor window use EditorWindow. Further explanation here. Whichever type you need, you’ll be subclassing.

Subclass It and Add the Boilerplate

Custom editor classes each have a bit of boilerplate you’ll need to add to get them working. For example, PropertyDrawers need EditorGUI.BeginProperty/EndProperty, Editors will need serializedObject.Update/ApplyModifiedProperties, and EditorWindows will need a MenuItem access and static Init (or other method if you’re only creating buttons without windows). Don’t forget the boilerplate or you may end up with an editor where the values never change (as is the case where you don’t ApplyModifiedProperties)!

Add Your Fields

Unity has a large number of pre-built fields for you to use in EditorGUILayout (and a few more like ProgressBar in EditorGUI). ReorderableLists can be super handy as well (add using UnityEditorInternal; to find them). You can even create your own.

Make It Your Own

Once you have your own editor, you can customize it beyond just the fields. You can add custom logic to validate input, show or hide fields based on certain conditions, or whatever else you’d like to do. One important note to keep in mind is that the variables stored in your custom editor are not persisted. For example, if you want to keep the state of your dropdown persisted in your custom Editor so you can keep going from where you left off the next time you open Unity, you’ll need to store that value in the script. It’s kind of ugly in my opinion, but you can clean it up with the following:

#region Editor variables
#if UNITY_EDITOR
#pragma warning disable 0414
[SerializeField]
bool showResolutionList = true;
#pragma warning restore 0414
#endif
#endregion

The region labels the area and can collapse it in certain IDEs. The preprocessor directive ensures you only use those variables in the editor and exclude them from your builds. The pragma warning can disable certain errors that come up if you never set or get certain fields directly (such as when accessing them through serializedObject.FindProperty). You can find the specific warning number to disable in the console. The SerializeField persists the variable and ensures you can get it through serializedObject.FindProperty (as in this example the field is private, so could not be accessed through target).

Quick Tips

Make sure all the fields you need are accessible to the Editor. They must be Serialized. (Public fields automatically are if they are of a serializable type. Private fields can be with [SerializeField].) You can make custom classes serializable with [System.Serializable] above the public class… class declaration.

You can access the script in your custom Editor with target (casted to the proper type). However, you’ll only be able to access fields you normally can (private fields won’t be accessible) and your edits will not be persisted unless you use EditorUtility.SetDirty(target);. Using FindProperty notation will automatically persist your changes.

A DelayedInt doesn’t modify the backend value until you hit enter or click off it. (The array size int field with standard arrays in an example of this.) This can be handy if you’re debugging values and you don’t want the value to update until you pick the new value. (Otherwise, if you backspace 1000 to enter 500, you’ll go through 100, 10, 1, 0, 5, 50, and 500).

Summary

There you go! You’re all set to make a custom editor in Unity! I usually find it helpful to see an example, so check out the Unity documentation for a PropertyDrawer, Editor, or EditorWindow for a few great ones.

Published inCode ExamplesDevelopment Tips

Be First to Comment

    Leave a Reply

    Your email address will not be published. Required fields are marked *