The automatic layout system in Unity's GUI is handled by the GUILayout class. Its methods are similar to the base GUI class but include automatic positioning and sizing for UI elements.
GUILayout Options
Options can be passed to GUILayout methods to control element sizing:
- Fixed Width/Height:
GUILayout.Width(300),GUILayout.Height(200) - Minimum Width/Height:
GUILayout.MinWidth(50),GUILayout.MinHeight(50) - Maximum Width/Height:
GUILayout.MaxWidth(100),GUILayout.MaxHeight(100) - Expand Width/Height:
GUILayout.ExpandWidth(true),GUILayout.ExpandHeight(false)
EditorGUI and EditorGUILayout
EditorGUI provides UI controls specific to editor tools, extending the functionality of GUI. EditorGUILayout is its auto-layout counterpart. Typically, these are used in conjunction with standard GUI calls within editor scripts. The primary difference between EditorGUI and EditorGUILayout is that the former requires manual Rect positioinng.
Official documentation for EditorGUILayout can be found in the Unity Scripting API.
Basic EditorGUI Controls
Labels and Selectors
- LabelField:
EditorGUILayout.LabelField("Label Text", "Displayed Value"); - LayerField:
selectedLayer = EditorGUILayout.LayerField("Select Layer", selectedLayer); - TagField:
selectedTag = EditorGUILayout.TagField("Select Tag", selectedTag); - ColorField:
chosenColor = EditorGUILayout.ColorField(new GUIContent("Title"), chosenColor, true, false, false);
using UnityEditor;
using UnityEngine;
public class EditorControlsWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Editor Controls")]
static void OpenWindow() {
GetWindow<EditorControlsWindow>("Editor Controls").Show();
}
int layerValue;
string tagValue;
Color colorValue;
void OnGUI() {
EditorGUILayout.LabelField("Sample Label", "This is content");
EditorGUILayout.LabelField("Another Label");
layerValue = EditorGUILayout.LayerField("Layer Selection", layerValue);
tagValue = EditorGUILayout.TagField("Tag Selection", tagValue);
colorValue = EditorGUILayout.ColorField(new GUIContent("Custom Color"), colorValue, true, false, false);
}
}
Enum and Integer Selection
- EnumPopup (Single-select):
myEnum = (MyEnumType)EditorGUILayout.EnumPopup("Choose Enum", myEnum); - EnumFlagsField (Multi-select):
myFlagEnum = (MyFlagEnumType)EditorGUILayout.EnumFlagsField("Multi-Select", myFlagEnum);Note: For flag enums, ensure values are powers of two (1, 2, 4, 8...). - IntPopup:
selectedInt = EditorGUILayout.IntPopup("Integer Option", selectedInt, new string[] {"Opt1", "Opt2"}, new int[] {10, 20}); - DropdownButton: Returns true on click.
if (EditorGUILayout.DropdownButton(new GUIContent("Click Me"), FocusType.Passive)) Debug.Log("Clicked");
public enum ExampleFlags
{
OptionA = 1,
OptionB = 2,
OptionC = 4,
ComboAB = 1 | 2,
}
public class SelectionWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Selection")]
static void Init() { GetWindow<SelectionWindow>("Selection").Show(); }
ExampleFlags singleSelect;
ExampleFlags multiSelect;
int popupInt = 0;
string[] labels = { "Option 100", "Option 200", "Option 300" };
int[] values = { 100, 200, 300 };
void OnGUI() {
singleSelect = (ExampleFlags)EditorGUILayout.EnumPopup("Single Enum", singleSelect);
multiSelect = (ExampleFlags)EditorGUILayout.EnumFlagsField("Multi Enum", multiSelect);
popupInt = EditorGUILayout.IntPopup("Integer Popup", popupInt, labels, values);
EditorGUILayout.LabelField("Selected:", popupInt.ToString());
if (EditorGUILayout.DropdownButton(new GUIContent("Action Button"), FocusType.Passive))
Debug.Log("Action Triggered");
}
}
Object Reference and Data Input Fields
- ObjectField:
myObject = EditorGUILayout.ObjectField("Reference", myObject, typeof(GameObject), false) as GameObject; - Input Fields:
intVal = EditorGUILayout.IntField("Int Input", intVal);floatVal = EditorGUILayout.FloatField("Float Input", floatVal);textVal = EditorGUILayout.TextField("Text Input", textVal);vec2Val = EditorGUILayout.Vector2Field("Vector2", vec2Val);rectVal = EditorGUILayout.RectField("Rectangle", rectVal);- Similar fields exist for
Long,Double,Vector3,Vector4,Bounds,BoundsInt.
- Delayed Input: Variants like
DelayedIntFieldupdate the value only when the user presses Enter or moves focus away from the field.
public class InputWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Input")]
static void CreateWindow() { GetWindow<InputWindow>("Input").Show(); }
GameObject linkedObject;
int integerInput;
float floatInput;
string textInput;
Vector2 vector2Input;
Rect rectangleInput;
int delayedInteger;
void OnGUI() {
linkedObject = EditorGUILayout.ObjectField("GameObject Reference", linkedObject, typeof(GameObject), false) as GameObject;
integerInput = EditorGUILayout.IntField("Integer", integerInput);
floatInput = EditorGUILayout.FloatField("Float", floatInput);
textInput = EditorGUILayout.TextField("String", textInput);
vector2Input = EditorGUILayout.Vector2Field("Vector2", vector2Input);
rectangleInput = EditorGUILayout.RectField("Rect", rectangleInput);
delayedInteger = EditorGUILayout.DelayedIntField("Delayed Int", delayedInteger);
EditorGUILayout.LabelField("Delayed Value:", delayedInteger.ToString());
}
}
Foldout and Toggle Controls
- Foldout:
isExpanded = EditorGUILayout.Foldout(isExpanded, "Section Title"); - Foldout Header Group: Provides a bold, highlighted header.
isGroupExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isGroupExpanded, "Group Title");... // Content inside groupEditorGUILayout.EndFoldoutHeaderGroup();
public class GroupingWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Groups")]
static void Launch() { GetWindow<GroupingWindow>("Groups").Show(); }
bool simpleFoldout = false;
bool headerFoldout = false;
void OnGUI() {
simpleFoldout = EditorGUILayout.Foldout(simpleFoldout, "Basic Foldout");
if (simpleFoldout) {
EditorGUILayout.LabelField("Content inside basic foldout.");
}
headerFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(headerFoldout, "Header Foldout Group");
if (headerFoldout) {
EditorGUILayout.LabelField("Content inside header group.");
EditorGUILayout.LabelField("This area is collapsible.");
}
EditorGUILayout.EndFoldoutHeaderGroup();
}
}
- Toggle:
boolState = EditorGUILayout.Toggle("Standard Toggle", boolState); - ToggleLeft:
boolState = EditorGUILayout.ToggleLeft("Left-aligned Toggle", boolState); - ToggleGroup: Encloses controls that are enabled/disabled by a master toggle.
groupActive = EditorGUILayout.BeginToggleGroup("Enable Controls", groupActive);... // Grouped controlsEditorGUILayout.EndToggleGroup();
public class ToggleWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Toggles")]
static void Display() { GetWindow<ToggleWindow>("Toggles").Show(); }
bool standardToggle = false;
bool leftToggle = false;
bool masterToggle = false;
void OnGUI() {
masterToggle = EditorGUILayout.BeginToggleGroup("Master Switch", masterToggle);
standardToggle = EditorGUILayout.Toggle("Standard", standardToggle);
leftToggle = EditorGUILayout.ToggleLeft("Left Aligned", leftToggle);
EditorGUILayout.EndToggleGroup();
}
}
Sliders and Help Boxes
- Slider / IntSlider:
floatVal = EditorGUILayout.Slider("Float Slider", floatVal, 0f, 1f);intVal = EditorGUILayout.IntSlider("Int Slider", intVal, 0, 100); - MinMaxSlider: Modifies two values via ref parameters.
EditorGUILayout.MinMaxSlider("Range", ref minVal, ref maxVal, 0f, 100f);
public class SliderWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Sliders")]
static void ShowWindow() { GetWindow<SliderWindow>("Sliders").Show(); }
float singleSlider = 0.5f;
int intSlider = 5;
float rangeMin = 2f;
float rangeMax = 8f;
void OnGUI() {
singleSlider = EditorGUILayout.Slider("Single Slider", singleSlider, 0f, 10f);
intSlider = EditorGUILayout.IntSlider("Integer Slider", intSlider, 0, 20);
EditorGUILayout.MinMaxSlider("Range Slider", ref rangeMin, ref rangeMax, 0f, 10f);
EditorGUILayout.LabelField($"Range: {rangeMin:F2} to {rangeMax:F2}");
}
}
- HelpBox: Displays a message box with an optional icon.
EditorGUILayout.HelpBox("Info message", MessageType.Info);MessageType can beNone,Info,Warning, orError. - Space: Adds vertical spacing.
EditorGUILayout.Space(20);
public class UtilityWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Utility")]
static void Open() { GetWindow<UtilityWindow>("Utility").Show(); }
void OnGUI() {
EditorGUILayout.HelpBox("Neutral information.", MessageType.None);
EditorGUILayout.Space();
EditorGUILayout.HelpBox("Informational note.", MessageType.Info);
EditorGUILayout.Space(30);
EditorGUILayout.HelpBox("Warning message.", MessageType.Warning);
EditorGUILayout.Space(30);
EditorGUILayout.HelpBox("Error alert.", MessageType.Error);
}
}
Advanced Controls and Layout
- CurveField:
animationCurve = EditorGUILayout.CurveField("Animation Curve", animationCurve); - Layout Blocks:
- Horizontal:
EditorGUILayout.BeginHorizontal();...EditorGUILayout.EndHorizontal(); - Vertical:
EditorGUILayout.BeginVertical();...EditorGUILayout.EndVertical();
- Horizontal:
- ScrollView:
scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);...EditorGUILayout.EndScrollView();
public class LayoutWindow : EditorWindow
{
[MenuItem("Custom Tools/Show Layout")]
static void InitWindow() { GetWindow<LayoutWindow>("Layout").Show(); }
AnimationCurve myCurve = AnimationCurve.Linear(0, 0, 1, 1);
Vector2 scrollPos;
void OnGUI() {
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
EditorGUILayout.LabelField("Long content area that can be scrolled.");
for (int i = 0; i < 20; i++) {
EditorGUILayout.LabelField($"Item number {i}");
}
EditorGUILayout.EndScrollView();
myCurve = EditorGUILayout.CurveField("Curve Editor", myCurve);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Left");
EditorGUILayout.LabelField("Center");
EditorGUILayout.LabelField("Right");
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginVertical(GUI.skin.box);
EditorGUILayout.LabelField("Top");
EditorGUILayout.LabelField("Middle");
EditorGUILayout.LabelField("Bottom");
EditorGUILayout.EndVertical();
}
}