Categories
Coding Tips Game Development Unity Tips

Unity C#, add custom buttons to your script’s inspector

So, you may have heard of Unity Editor programming, it is a powerful part of the engine that allows you to make custom tools, windows, inspectors and more. This can really improve the workflow of your game’s development. What you’ll find is that the topic of editor code is rather vague, there are some tutorials but a lot of it is googling and documentation reading to get what you need. It is rare for someone to have the same editor needs as yourself. Ideally, you’ll already be pretty confident with Unity and C# before going into editor code. But this post should give you the very basics for adding some buttons to a script to run methods both in and out of runtime for testing purposes. Which is a very handy tool when needing to check or debug things in your game.

Script placement in your project

To start with you need to know how to manage editor scripts. Unlike normal Monobehaviour’s which can be placed anywhere in your project and build fine. Editor scripts MUST be placed in or under a folder labelled Editor. You can have as many of these as you like and put them anywhere you want but all your editor scripts must be under one if you want to build your game, otherwise Unity will not allow you to make a build until you correct this issue. So, all of the following locations would work:

  • Editor/
  • Editor/SomeDirectory/
  • SomeDirectory/Editor/
  • SomeDirectory/Editor/AnotherDirectory/

Making a C# script into an editor script

A common naming convention for editor scripts is to suffix them with the work Editor. So, your normal C# script in Unity is going to be laid out like so, unless you have a custom template script template setup:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MyCustomEditor : MonoBehaviour 
{
	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

To change this into an editor script we have to change a few things. The first thing we are going to do is add an additional using definition for the unity editor namespace, called UnityEditor. The next change is the scripts inheritance, instead of inheriting from MonoBehaviour you’ll be inheriting from Editor. Next, as we are not inheriting from MonoBehaviour anymore you’ll want to remove the start and update functions/methods. By now your script should look like this and we are ready to start writing the code for the custom inspector:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;

public class MyCustomEditor : Editor
{
}

Making a button

For those who have done editor code before you’ll notice we haven’t added the custom editor attribute yet, we’re doing that next. We’re going to assume that this editor class will be adding a custom inspector to a class called MyCustomScript. So, you’ll first want to add an attribute to the script like so to define that this editor script is a custom editor of the MyCustomScript class:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;

[CustomEditor(typeof(MyCustomScript))]
public class MyCustomEditor : Editor
{
}

Next, we are going to get a reference to the script that we are going to be editing which we are going to be getting via casting the target script. Being honest I’m not 100% sure what this does but it works. You can get the script via serializedObject as well, but that’s a topic for another post. You’ll want to add a cached reference just like you would in a normal script, then there are two ways you can write the cast, it’s really up to your preference for how you write it, both of the following work just fine. In my example we are going to get the reference in the OnEnable function as we only need to get it once really:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;

[CustomEditor(typeof(MyCustomScript))]
public class MyCustomEditor : Editor
{
	private MyCustomScript script;

	private void OnEnable()
	{
		// Method 1
		script = (MyCustomScript) target;

		// Method 2
		script = target as MyCustomScript;
	}
}

Now that we have a reference to the script, we can now start making edits to its editor view. In this example we’re going to override the OnInspectorGUI method to draw our custom buttons. As the name suggests the method handles the inspector visuals for the script we are targeting. You can see the default inspector by calling the base implementation. Some IDE’s like Rider will put the base in when you create the method when using auto-complete. Next, we actually make the button itself. For this we are going to use GUILayout.Button which requires a string for the button label and has a variety of overloads that allow for customisation. All buttons in editor code are just if statements, so when pressed the button will perform the code for that if statement being true. You’d write this like so:

// Button with a blank label.
if (GUILayout.Button(""))
{

}

// Button with label showing "MyButton"
if (GUILayout.Button("MyButton"))
{

}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;

[CustomEditor(typeof(MyCustomScript))]
public class MyCustomEditor : Editor
{
	private MyCustomScript script;

	private void OnEnable()
	{
		// Method 1
		script = (MyCustomScript) target;
	}

	public override void OnInspectorGUI()
	{
		if (GUILayout.Button("MyButton"))
		{
			
		}

		// Draw default inspector after button...
		base.OnInspectorGUI();
	}
}

With that all in place, now all you need to do is add the implementation for button to do stuff. This works just like you’d expect; you can all methods, edit variables/properties ectara, using the reference we setup earlier like so:

// Button with label showing "MyButton"
if (GUILayout.Button("MyButton"))
{
	target.SomePublicOrInternalMethod();
	target.BoolProperty = true;
	target.someIntVariable = 10;
}

And that’s about it, you now have an editor button on the inspector of your script. You can add as many as you like and have them do anything you want really. You can also style them, make them have custom width, heights, colours, images etc. Just to quickly cover some of the essentials, below are some samples to make the buttons look cooler xD

if (GUILayout.Button("MyButton1"), GUILayout.Width(120)) // defines a width of 120 for the button
{
			
}

if (GUILayout.Button("MyButton2"), GUILayout.Heigth(120)) // defines a heigth of 120 for the button
{
			
}

if (GUILayout.Button("MyButton3"), GUILayout.ExpandWidth) // defines that the button will expand to any free space
{
			
}

EditorGUILayout.BeginHorizontal();  // Start a horiziontal group, like how a horizontal layout group for UI works 
GUILayout.FlexibleSpace();  // Auto fills any gaps left (kind of centers the buttons)

if (GUILayout.Button("MyButton4"))
{
			
}

if (GUILayout.Button("MyButton5"))
{
			
}

GUILayout.FlexibleSpace();  // Auto fills any gaps left (kind of centers the buttons)
EditorGUILayout.EndHorizontal();  // Ends a horiziontal group, like how a horizontal layout group for UI works 

GUI.color = Color.green;  // Changes the button colour to green
if (GUILayout.Button("MyButton6")) 
{
			
}
GUI.color = Color.white;

GUI.backgroundColor = Color.green;  // Changes the button background colour to green, keeps the text the default colour for the editor style.
if (GUILayout.Button("MyButton7")) 
{
			
}
GUI.backgroundColor = Color.white;

Leave a Reply

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