Using EditorGUI and EditorGUILayout for Unity Editor Extensions

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 DelayedIntField update 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 group EditorGUILayout.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 controls EditorGUILayout.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 be None, Info, Warning, or Error.
  • 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();
  • 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();
    }
}

Tags: unity Editor Development EditorGUI EditorGUILayout gui

Posted on Tue, 20 Oct 2026 16:28:02 +0000 by y4m4