Customizing that Editor - Intro Tutorial

Unity is a great tool. Within a few minutes of introduction a person with some development skill can learn how to create a custom script, attach it to an object and go. The inspector presents all the internals you will need to change and tweak your game.


But not always.


As you get deeper into game development there are situations where the built in inspector cannot handle all the data structures in your custom script. And situations where an addition to the editor in general would be helpful. Take a look at Cinemachine - that used to be an addon separate from Unity all together. It adds menu items, gizmos, customize inspectors and all of them are not default into Unity.


Custom editors can help you clean up your inspector interface, ease your level designers quality of life improving the editor, create new tools for use within the unity editor and allow you to edit advanced objected in the inspector that you have created, that Unity has no prior knowledge about.


I am making an escape room style adventure game and quickly realized I would be requiring custom editors. I have scripts that have other objects as member variables and the built in inspector may be able to handle editing an Integer but selecting one of 10 subclasses based on a parent class was beyond the built in abilities. At the same time I had reached some of my own code design decisions I ran across this tutorial: Unity Adventure Game Tutorial The tutorial is long, in depth and gave me a ton of ideas but I realized a lot of the tutorial was not the code for the game itself, but the code to edit the scripting for the game through custom editors.


For this example here is the custom inspector for a combination lock:



There are not many elements involved. How many digits and the answer to the digits and the reactions to do if the lock opens. I will not touch on the Reactions section in this post as that gets into subeditors in the main editor and deserves its own post.


Note: Make sure you save all custom editor scripts in a folder called "Editor" (anywhere in your hierarchy). If you do not Unity will try to include your editors in the full build of your game and it will not build properly. I learned this the hard way.


To start an editor you do not need much, use the UnityEditor namespace and declare that you are creating an editor:

Code
  1. using UnityEditor;
  2. [CustomEditor(typeof(ComboLock))]
  3. public class ComboLockEditor : Editor

Here I am saying that I am creating an editor (derived from Unity's Editor class) and saying it will be for the ComboLock object.


And you are done! Well not quite. The next step is to tell your editor what it is allowed to edit. To do so you declare variables of the type SerializedProperty what are set to the properties in the object you are editing.


Code
  1. private SerializedProperty dialAnswerProperty;
  2. private SerializedProperty reactionsProperty;
  3. private void OnEnable()
  4. {
  5. dialAnswerProperty = serializedObject.FindProperty("dialAnswer");
  6. reactionsProperty = serializedObject.FindProperty("reactions");
  7. }

Ignoring the reactions property for now what is important to get here is that "dialAnswer" must match the exact variable name in my combo lock class. In this case it looks like:

public int[] dialAnswer;

Unity knows how to edit an array of integers but I could have further customized this section if I wanted to.


So this is great, we have an editor. It knows what we want to edit, but the big question; how do we edit it?


In any inspector custom editor you will override a function called OnInspectorGUI. This function is responsible for drawing the GUI when your object is displayed in the inspector. There are a lot of options for how to customize the look and feel of the GUI so I would refer to the Unity manual to get some ideas. I will not get into those in this post.


Code
  1. public override void OnInspectorGUI()
  2. {
  3. serializedObject.Update();
  4. EditorGUILayout.PropertyField(dialAnswerProperty, true);
  5. EditorGUILayout.Space();
  6. serializedObject.ApplyModifiedProperties();
  7. }

Here is an abridged section of my OnInspectorGUI (I have removed the reactions section for now). The Update and ApplyModifiedProperties are telling Unity to display and save changes that have been made. The "serializedObject" property comes from the base Editor class and is a reference to the current object being edited. So in this example it would refer to a GameObject with a ComboLock script attached to it. This can be useful for more advanced functions (foreshadowing to the Reactions post later!).


The rest of the code is somewhat self explanatory. Display the property we defined earlier (as mentioned if I wanted a fancier int array editor this is what I would change). And I lied, one small GUI element as an example EditorGUILayout.Space will put a blank line in your GUI in my case between the dial answer and the reactions section once I add it in.


And that is it! You have a custom editor. This example is trivial but shows how the basics are created. I have included the full code (minus Reactions) at the bottom.


I would suggest try creating editors on simple objects to learn more. Try it with ints, strings, floats, arrays, Lists and any other data type you are interested in. If you look up the Unity manual for the EditorGUILayout you will see a lot of formatting functions. You can add custom labels, drop downs, fold ups, horizontal and vertical layout options. Realize everything you see in the Unity inspector is done using these same methods.


I hope this was useful and please leave comments and questions if you have any. If there is interest I will continue this tutorial and write about how the custom reactions section works where I create new objects attached to my combo lock that themselves require custom editors. If you made it to then end, thanks for reading!



Full code example:

Code: ComboLock
  1. public class ComboLock {
  2. public int[] dialAnswer;
  3. private ComboLockDial[] dials;
  4. }

Comments 4

  • Thanks for the interesting tutorial and I hope you go more in-depth with this in the future. It's a topic I haven't touched yet and I think the reason for it is that I'd rather do more in code than in the graphical environment. I know it might be easier for debugging and on-the-fly changes but for some reason I don't like the idea of something not in code influencing the way the game behaves, sometimes in a significant way ;) I'd rather look for bugs in my logic than in some sliders and checkboxes, even though I understand the benefits and ease-of-use of this approach. I probably will come across a challenge that's better solved using custom editors and I will get back to your tutorial then ;)

    • In my situation I would have had to hard code upwards of 50-100 objects in the escape room and doing so in only code would be onerous and brittle.


      The big advantage I found was I could create/link objects together. As in the example above I could hook no reactions, 1 reaction or 50 reactions to the lock opening. And change it lock to lock. If I had to do it in code every lock in the room would need its own script.


      Each method has its own place though.

  • Very informative Gamblor!

    Love to read more about stuff like this in the future, if you are planning more! :D

    • Thanks, I plan to write a short post about the problem I was working with you on, and a longer one about subeditors later.