EditorGUI, EditorGUILayout, GUI, GUILayout... pshhh... WHEN TO USE WHAT?!

When writing editor scripts, I see scripts using EditorGUI, or even just GUI sometimes. And yet other times it’s EditorGUILayout, etc. It’s just so confusing because, a lot of times there’s common stuff between those classes, for example you could get a label from GUI.Label and GUILayout.Label why??! what’s the difference? why have 2 classes, do the same thing??

And yet other times, there’s certain functionality that’s only available in one class, but not in the other, and so you end up forgetting where the functionality you want lies. Or other times they do exist, but with subtle differences between them. Like EditorGUI.BeginDisabledGroup and EditorGUILayout.BeginToggleGroup.

Can somebody please explain, when to use which class? especially in editor scripting. When and why would I want to use EditorGUI instead of EditorGUILayout, or vise versa? can I use both when writing a custom inspector/editor window? is there a benefit for using one over the other? am I the only one that’s confused and feeling a bit lost?

Look at this code snippet for example:

	GUILayout.Label("Base Settings", EditorStyles.boldLabel);
	myString = EditorGUILayout.TextField("Text Field", myString);
	group_timeEffect = EditorGUILayout.BeginToggleGroup("Time effect", group_timeEffect);
	EditorGUI.BeginDisabledGroup(isDividedOvertime); //<---
	isPermanent = EditorGUILayout.Toggle("Permanent", isPermanent);
	tick = EditorGUILayout.FloatField("Tick", tick);
	EditorGUI.EndDisabledGroup(); //<---
	EditorGUI.BeginDisabledGroup(isPermanent); //<---
	isDividedOvertime = EditorGUILayout.Toggle("Overtime", isDividedOvertime);
	duration = EditorGUILayout.FloatField("Duration", duration);
	EditorGUI.EndDisabledGroup(); //<---
	EditorGUILayout.EndToggleGroup();

(from J’s answer)

The code used GUILayout.Label, but I could get a Label from GUI.Label, it used EditorGUILayout.TextField, but I could also get a TextField from EditorGUI, it used EditorGUILayout.Toggle, but I could get a Toggle from GUI.Toggle, GUILayout.Toggle AND EditorGUI.Toggle! I hope you’re feeling me now…

The doc is just super retarded, and does a very excellent job at explaining things in detail, providing tons of great examples.

Thanks for your help time.

EditorGUI.Toggle and GUI.Toggle looks different but I hear your frustration as I’ve been working with Editor GUI code a lot and know where you’re coming from. Look at this example for example, which does a toggle with EditorGUILayout and GUILayout. Not only are the parameters swapped around but the output looks different too. EditorGUILayout.Toggle is used in inspectors to get a uniform “Label” - “Content” structure just like the (well, most, at least) other EditorGUI methods.

using UnityEngine;
using UnityEditor;

public class MyEditor : EditorWindow {
	[MenuItem("Example/Show Window")]
	public static void ShowWindow () {
		GetWindow<MyEditor> ().Show ();
	}

	void OnGUI() {
		EditorGUILayout.Toggle ("EditorGUILayout.Toggle", false);
		GUILayout.Toggle (false, "GUILayout.Toggle");
	}
}

19619-toggle.png

I think the best advice I can give you is to get a feel for the different classes and accept that you may have to jump around in them to find what you need. Don’t be afraid of mixing class usage. In the case of BeginDisabledGroup, it has nothing to do with laying out of elements, so I guess that’s why it ended up in EditorGUI rather than EditorGUILayout.

It is what it is. We have to accept it and it will add a little learning curve to us all, but once we got warm with it, it’s relatively easy to get around and being productive.


Per the discussion in the comments, here’s how you can encapsulate your GUI code into reusable classes that hopefully are easier to manage.

The idea is that you should only worry about how complex the first class looks. The IGUI interface is just for convenience here, to allow all GUI objects to be added to a list. I include a button and a text field. As you can see, the editor only has one variable to each GUI control, username, realname and registerButton. They are created during OnEnable, and a callback is set up so button clicks will be caught by RegisterUser. RegisterUser will just demonstrate that it pulls data from the two text fields.

This is a pretty minimal example - you can flavour it in any way you want. Perhaps you want to expose styles to your objects too for instance. Perhaps you want to be able to disable individual components? And so on.

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

public class MyEditor : EditorWindow {

	GUITextField username;
	GUITextField realname;
	GUIButton registerButton;

	// Optional, but may be convenient.
	List<IGUI> gui = new List<IGUI>();

	[MenuItem("Example/Show Window")]
	public static void ShowWindow () {
		GetWindow<MyEditor> ().Show ();
	}

	void OnEnable() {
		username = new GUITextField ();
		username.label.text = "Username";
		username.text = "JDoe";

		realname = new GUITextField ();
		realname.label.text = "Real name";
		realname.text = "John Doe";

		registerButton = new GUIButton ();
		registerButton.label.text = "Register";
		registerButton.Clicked += RegisterUser;

		gui.Add (username);
		gui.Add (realname);
		gui.Add (registerButton);
	}

	void RegisterUser()
	{
		var msg = "Registering " + realname.text + " as " + username.text; 
		Debug.Log (msg);
	}

	void OnGUI() {
		foreach (var item in gui)
			item.OnGUI();
	}
}

public interface IGUI {
	void OnGUI();
}

public class GUITextField : IGUI {
	public string text = "";
	public GUIContent label = new GUIContent();

	// Unused in my example, but you may want to check if
	// a textbox becomes empty for example.
	public event System.Action<string> TextChanged;

	public void OnGUI() {
		// Also I wanted to show you BeginChangeCheck and EndChangeCheck 
		// which is the Unity GUI way of checking if a GUI control changed...
		EditorGUI.BeginChangeCheck ();
		text = EditorGUILayout.TextField (label, text);
		if (EditorGUI.EndChangeCheck () && TextChanged != null)
			TextChanged (text);
	}
}

public class GUIButton : IGUI {
	public GUIContent label = new GUIContent();
	public event System.Action Clicked;

	public void OnGUI() {
		if (GUILayout.Button (label) && Clicked != null)
			Clicked ();
	}
}

Did you read Unity - Manual: IMGUI Layout Modes ?

GUILayout and GUI are deliberately mirrors of each other - one for fixed layout and one for automatic layout. Same with EditorGUI and EditorGUILayout, but those are specifically designed for adding GUI in the editor window.

They don’t do the same thing…GUI uses absolute rect coordinates, GUILayout is for auto-layout. You use whatever works better for you and your script. BeginDisabledGroup is under script control, BeginToggleGroup lets the user toggle a group. BeginDisabledGroup isn’t related to auto-layouting so it wouldn’t be in the GUILayout class.

The EditorGUI classes are for editor use only. You can sort of think of it as a sort of sub-group of the GUI class that does stuff specifically for editor scripts, whereas GUI is general-purpose and can be used for both runtime scripts and editor scripts.