Crossposted on App Goodies
GUI code written will work for both Custom Inspector and Custom Window without any compile errors. So for example, if I’ve shown a code snippet for Custom Inspector, it doesn’t mean it won’t work for the Custom Window. Just note that in some cases it may lead to undesired results.
Making a Custom Inspector
Like an ordinary script, Custom Inspector it can be attached to any entity that is listed in the Hierarchy window. Data collected from that inspector can then be used during the play mode.
Unlike a custom window, custom inspector requires two scripts:
IMGUI – renders all custom GUI components (e.g, buttons, drop-down etc.) – it communicates with a MonoBehaviour script, allowing you to read and write variable values from it. IMGUI script cannot be attached as a component
MonoBehaviour – a script with all variables and functions, however, when it’s attached to the GameObject, custom IMGUI is being drawn instead of an ordinary inspector.
Now, with a brief explanation behind, let’s get to coding bit!
Setting Up
As mentioned earlier, we must create two scripts. I am going to create a script that allows you to generate your own NPC type, his base health etc. So I am going to name my scripts NpcClassScriptand NpcClassEditor.
Place NpcClassEditor into an “Editor” folder. This will prevent Unity from trying to compile the inspector script itself. Remember to keep NpcClassScript outside of “Editor” folder, otherwise, it won’t work!
Open NpcClassScript and declare few variable types:
public string npcName = "Bob"; public int npcHealth = 10; public float npcSpeed = 4.5f; public bool isEnemy = false; public GameObject npcObject; public AnimationClip defaultAnimation; public Sprite npcIcon; public class_type_list classType = class_type_list.villager; public enum class_type_list { warrior, archer, tank, wizard, villager }
As usual, we would declare our variables above Start() and Update(). It’s still a MonoBehaviour script, so if we attach it to any GameObject, we’ll see a default inspector with all the variables listed.
With all necessary variables listed, we’re good to go!
Open NpcClassEditor – this is where IMGUI and Monobehaviour scripts are different.
Before we start, we must include UnityEditor. This will grant us additional functions, allowing us to create custom GUI components such as text fields and buttons.
Remove both Start() and Update() functions, they’re not needed for a Custom Inspector because the script itself does not compile and run in the final build. In other words, NpcClassEditor serves as an alternative view of NpcClassScript.
Next, we must replace MonoBehaviour with Editor . This tells Unity that NpcClassEditor is an Editor script.
To this point, your script should look something like this:
using UnityEngine; using System.Collections; using UnityEditor; public class NpcClassEditor : Editor { }
Right above the public class, we must add the following line of code:
[CustomEditor(typeof(NpcClassScript))]
This will tell Unity that we’re going to reference our variables from NpcClassScript. Inside of our NpcClassEditor, create a public override void OnInspectorGUI(). This is where all the action will take place.
To make it easier for us to reference variables from NpcClassScript in the future, we must declare the variable of the following type:
using UnityEngine; using System.Collections; using UnityEditor; [CustomEditor(typeof(NpcClassScript))] public class NpcClassEditor : Editor { public override void OnInspectorGUI() { NpcClassScript npcScript = (NpcClassScript)target; } }
Now if you want to access a variable from NpcClassScript, we must type npcScript beforehand.
Now if you check out the inspector, you’ll notice that it’s blank:
This means that OnInspectorGUI overrides the NpcClassScript’s inspector. Because there OnInspectorGUI has nothing to draw (yet), the inspector window is empty (core variables are overridden by this function)
Unlike ordinary MonoBehaviour scripts, you can’t directly open an editor script to edit the code. This gives your Custom Inspector a nicer and more professional look!
With the core part of NpcClassEditor written, we can start adding GUI components!
Unlike in a Custom Window, we must use EditorGUILayout() function. While it’s possible to use GUI (where x, y, w, h must be entered manually), it won’t lead to desired results as it will use the x, y values from the whole inspector. As a result, your GUI components can appear at the very beginning of the inspector window, overlapping other components.
Let’s start with few basic components such as int, float, label etc.
Labels
Label is a simple text which is normally used to divide variables to categorize them. To create a label, add the following:
EditorGUILayout.Label("NPC Info");
The result:
Text Fields
Textfields require a bit more work to get to work. I will show you in a moment.
First off, in order to create a text field with a label attached to it on the right side, add this:
EditorGUILayout.TextField("NPC Name", npcScript.npcName);
If you let Unity compile changes, you’ll notice a text field with its own label has been added with “Bob” written inside. However, if you try to type something in, you’ll notice that there are no changes.
This is because npcScript.npcName returns a string and writes it into our text field. And, as a result, it does not accept changes.
To solve this, simply add npcScript.npcName before making a EditorGUILayout.TextField(). Try again, and you’ll now be able to type inside! Like so:
npcScript.npcName = EditorGUILayout.TextField("NPC Name", npcScript.npcName);
Buttons
To add a button simply use GUILayout.Button(). But unlike other GUI functions, we must wrap it inside of if () { }
if (GUILayout.Button("Debug the name")) { //do stuff Debug.Log(npcScript.npcName); }
When the button is pressed, it’ll return true. In my case, it’ll write a debug NPC’s name.
But what if we want to change the size of the button? It’s simple! Simply add EditorGUILayout.Width() and/or EditorGUILayout.Height() inside of the Button() after the name.
if (EditorGUILayout.Button("Big Fat Button", EditorGUILayout.Width(150), EditorGUILayout.Height(30))) { Debug.Log("Big fat button says: " + npcScript.npcName); }
You can see changes after compilation.
Floats, Ints and Bools
Declaring floats, bools and ints involve the same principle as a text field we made before.
//float field npcScript.npcSpeed = EditorGUILayout.FloatField("NPC Speed", npcScript.npcSpeed); //int field npcScript.npcHealth = EditorGUILayout.IntField("NPC Health", npcScript.npcHealth); //boolean field npcScript.isEnemy = EditorGUILayout.Toggle("Is Enemy", npcScript.isEnemy);
And we get to edit float, int and a boolean values respectively!
Dropdown Boxes
If you wish to have a drop-down field, it can be achieved by:
npcScript.classType = (NpcClassScript.class_type_list)EditorGUILayout.EnumPopup("Class Type", npcScript.classType);
Return back to Unity and you’ll see a difference:
Note that I have defined class_type_list in NpcClassScript. In order to reference it from NpcClassEditor, I simply did NpcClassScript.class_type_list . You can use this method if you want to reference your own class.
Using ObjectFields
FloatField, IntField, Toggle, TextField possibilities are endless! Or not…You might’ve noticed that EditorGUILayout is missing some other variable types such as GameObjectField, AnimationClipField etc. Where the heck did they go?
ObjectField() to the rescue!
It allows you to draw more GUI types such as GameObject field, Sprite field and more! However, it takes more work to get the job done, but it’s worth it!
Say, we want to add a GameObject field to NpcClassEditor