- Home /
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.
Answer by Statement · Dec 21, 2013 at 09:45 PM
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");
}
}
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 ();
}
}
If you just wanted to know about usage of automatic layout, tanoshimis and Eric5h5s answers are more appropriate for you.
Thanks for taking the time, that was awesome! I actually gave up on UnityGUI quite early on when I began learning Unity. I saw no way (at least an easy way) of doing really complex UIs in it. So I turned to NGUI. But now I'm learning editor scripting, when I realized that I'm stuck with the same old crap.
The problem is, it's very confusing. Confusion will get cleared out with experiment no doubt. But what's gonna happen is, all the time we put to learn and experiment with the current UnityGUI, will be wasted when the new UnityGUI comes out! (which is based on NGUI) - but yet you can't wait for it to come out and do your things, you have to get your stuff done! - not just that, once the new thing comes out, you're gonna have to redesign everything you had before, to adopt with the new code... (very painful experience, done it twice)
I just hope the new GUI will also make editor scripting and creating custom windows/inspectors easier as well...
The new GUI is likely only going to be for in-game, but this is just a speculation on my part as I faintly remember some talk where it was explained that editor gui is still going to be using the old system.
Here's a tip: If you want to make a kind of retained GUI, you can make wrapper classes for things you want to use. You could make a GUITextField class that holds a string and it manages updating the string for you as long as you call its OnGUI function. It's a very cheap but pretty robust way of making your UI in a way that gets somewhat clean to read. You can expose events to hook up with, like, if the text field was changed.. if a button was pressed.. if a checkbox was ticked.. and so on.
For small GUI snippets, I usually just muscle it out and write it out in full even if it's somewhat of a pain. If I want to make a bigger or cleaner GUI effort, I wrap GUI calls into managable classes that I write myself. I like reinventing the wheel because each time I try a different approach or just a slightly different flavour to it. But that's me, and I prefer to do it that way. I don't sit on any knowledge of third party helpers, so I can't help you there. You could write yourself a reusable GUI lib and use that for future projects.
If you encapsulate one GUI element into an object, at least all of the data you need for that object will be contained within the object and not spread out as variables shared with the rest of the logic for your UI. It easily becomes a nightmare to keep track of all the different styles, rects, values and other state values in your code if you just write it out in the most naive way.
Give me a few moments and I can show you an example (Ill update my answer when its done)
A ScriptableWizard is always drawn on top of the Unity editor regardless of focus, whereas an EditorWindow is not.
Answer by tanoshimi · Dec 21, 2013 at 09:22 PM
Did you read http://docs.unity3d.com/Documentation/Components/gui-Layout.html ?
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.
Thanks for the link. $$anonymous$$akes things a bit clearer.
Answer by Eric5h5 · Dec 21, 2013 at 09:35 PM
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.
So... Let's say I'm writing an editor window and I wanted to display X, and found out that I could do GUI.X
, EditorGUI.X
, etc.X - Can I safely use any of those, and assume that things will go fine? o.o
You can use either of them. The difference is only in style. EditorGUI offer more Editor specific functionality, such as setting object references. But EditorGUI doesn't have a button, so you'd have to use GUI.Button. Don't get afraid of mixing EditorGUI and GUI. In the end, it's just some piece of GUI showing up. If you want to be consistent with Unitys GUI, stick with EditorGUI wherever you can, and if you need something like a button, use GUI.Button. You can also pass in some nice little Editor styles like GUILayout.Button ("Cool looking button", EditorStyles.$$anonymous$$iButton);
Your answer
Follow this Question
Related Questions
Best way to offset GUI element from scrollbar in custom inspector? 0 Answers
Is it possible to store and display EditorGUILayout.Toggles? 0 Answers
EditorGUI like light explorer window 1 Answer
GUIStyle doesn't work when renamed. What to do here? 1 Answer
Recreate default editor look manually without base.OnInspectorGUI [UnityEditor] 2 Answers