Custom Editor Windows - Part 1
Build your own Unity Editor windows.
The documentation has moved to: https://mitschmr-studios.io/documentation/api-guides/customeditorwindowspart1.html
This version will no longer be updated and maintained.
This topic is split into two parts. In the first part, I want to introduce you to how to build your own Unity editor windows. Part two shows you how to make custom Inspector GUIs.
- Install Unity
- Install IDE (I use Visual Studio 2019)
- Import Game Creator (optional, only if needed for the window)
- Import and enable modules (optional, only if needed for the window)
You all know the Scene window, the Inspector and many more windows in Unity. But what is actually an Editor window?
An Editor window is a window in Unity that shows certain content. According to Unity, this includes three simple steps:
- Create a script that derives from EditorWindow
- Use code to trigger the window to display itself
- Implement the GUI code for your tool
Normally, when a script derives fromEditor
and you want to start building your project, the build will fail. This is because the classEditor
is not available in built versions of the game, only in the Unity Editor. We have to place the script in a folder with the nameEditor
, so it doesn't get included in the built game. But why the nameEditor
? Unity uses so called Special folder names to tread a folder's content in a special way. See Unity Special Folders for more information.
The same applies to the class
EditorWindow
. But it is not as easy as Unity tells you to build these windows. But let's start from the beginning. You should now know that we need a folder called Editor for displaying editor window. Add this folder to your scripts folder and create a new C# script. I will name my script TutorialWindowEditor.cs. Let it derive from
EditorWindow
, add the using statement for UnityEditor
and delete the Start and Update methods. Your script should now look like this: using UnityEditor;
public class TutorialWindowEditor : EditorWindow
{
}
In order to show a window, Unity needs a menu item which calls the
ShowWindow()
method. With a menu item, you are able to open a window from anywhere in top bar of the Unity Editor. The default behavior is to show already opened windows of this type. Let's do this: [MenuItem("Window/Tutorial Window")] // Adds a menu entry under Window
public static void ShowWindow()
{
EditorWindow.GetWindow(typeof(TutorialWindowEditor), false, "Tutorial Window");
// Because we derive from EditorWindow, "EditorWindow." is not necessary,
// below code works too.
// GetWindow(typeof(TutorialWindowEditor));
}

Add your class name to
typeof(<your class name>)
. Otherwise it won't work, because Unity most likely won't find this type (class). We also added a title to the window, so it doesn't show the class name. When you switch back to Unity and let it compile, you can open your window from the path you entered in the menu item. If you click again on the button, it sets the focus on the window because there is already one opened. Editor windows use the method
OnGUI()
to render the content of a window. This is where the actual code is written. There are many different elements you can add, both in EditorGUI and EditorGUILayout. The difference between them is that EditorGUILayout is auto laid out, which means it adjusts automatically to the window size. void OnGUI()
{
EditorGUILayout.LabelField("Color");
EditorGUILayout.ColorField(new Color(1,1,1));
EditorGUILayout.LabelField("Text");
EditorGUILayout.TextField("Change this text");
}
Result:

This looks ok for now, but it doesn't save the values, they get overwritten all the time. Let's change this behavior. First, add a private color and text variable before the menu item, set the GUI elements to display the values and change the values accordingly to the input.
private Color color = new Color(1, 1, 1); // You can set any color you want
private string text = "Change this text"; // You can set any text you want
<...>
void OnGUI()
{
EditorGUILayout.LabelField("Color"); // Title
color = EditorGUILayout.ColorField(color); // Color field
EditorGUILayout.LabelField("Text"); // Title
text = EditorGUILayout.TextField(text); // Text field
}
When we now change the values, they are saved until the window gets closed.

Editor windows contain similar methods like gameobjects. Visit EditorWindow for all methods and more. Here is a list of the (in my opinion) most important methods with the description and their use cases:
Name | Description | Use cases |
Awake() | Called as a new window is opened | Execute code when window is opened |
Close() | Closes the window | Close window |
GetWindow() | Gets a window of a certain type | Show already opened window / create new window |
OnDisable() | Called when window goes out of scope | Clear / save variables |
OnEnable() | Called when object is loaded | Load variables / data |
OnGUI() | Render your window code | Window design |
Repaint() | Repaints the window | Update window if content has changed |
Example: Reading data from disk should NOT happen in OnGUI, because OnGUI gets called up to several times per frame. Do this in i.e. OnEnable(), which gets only called when the window is loaded.
You still need the basic class, menu item, ShowWindow() etc.
private static readonly GUIContent[] TAB_NAMES = new GUIContent[]
{
new GUIContent("Tab 1"),
new GUIContent("Tab 2"),
new GUIContent("Tab 3"),
new GUIContent("Tab 4")
};
private int tabIndex = 0;
void OnGUI()
{
tabIndex = GUILayout.Toolbar(tabIndex, TAB_NAMES);
switch (tabIndex)
{
case 0: DoSomething1(); break;
case 1: DoSomething2(); break;
case 2: DoSomething3(); break;
case 3: DoSomething4(); break;
}
}
// Void DoSomething1(), DoSomething2()...

private Vector2 _scrollPosition;
private GUIStyle _tutorialFont = new GUIStyle();
void OnEnable()
{
_tutorialFont.fontSize = 13;
_tutorialFont.wordWrap = true;
_tutorialFont.margin = new RectOffset(5, 5, 0, 0);
}
void OnGUI()
{
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
// Split for better readability
EditorGUILayout.LabelField("Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " +
"sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. " +
"Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. " +
"At vero eos et accusam et justo duo dolores et ea rebum. " +
"Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."
, _tutorialFont);
EditorGUILayout.EndScrollView();
}

private Animation _animObject;
private Actions _actionObject;
private ScriptableObject _scriptableObject;
void OnGUI()
{
_animObject = (Animation)EditorGUILayout.ObjectField(_animObject, typeof(Animation), false);
_actionObject = (Actions)EditorGUILayout.ObjectField(_actionObject, typeof(Actions), true);
_scriptableObject = (ScriptableObject)EditorGUILayout.ObjectField(_scriptableObject, typeof(ScriptableObject), false);
}
