Empty space at the top of a custom property drawer layout?

I’m talking about the empty space it leaves here above the "Text" label, which seems to be caused by the CustomPropertyDrawer for the localized text class:

Here I put a (absolute positioned) label right at the position passed to the CustomPropertyDrawer OnGUI method:

Is there a reason why the GUILayout methods skip a line?

4 Answers

4

Here we are 5 years later.

I was facing the same problem and here is a hacky, yet simple and effective way to fix this issue:

public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { return 0; }

Add this override to the PropertyDrawer class and extra spaces will be gone (if you face any problems, do let me know)

or, if you want to be extra elegant: public override float GetPropertyHeight(SerializedProperty property, GUIContent label) => 0;

Thanks for the super precise fix!

Hi! Looks like the problem is not your label field, but the text input field after it. For some reason it is not drawing the full height of the space you have allocated for it. Not sure if it’s affecting this case but, you should not use EditorGUILayout inside of a PropertyDrawer. Just use the corresponding EditorGUI methods and manage the rectangles yourself. For example:

EditorGUI.BeginProperty(position, label, property);
Rect labelRect = position;
labelRect.height = EditorGUIUtility.singleLineHeight;
EditorGUI.PrefixLabel(labelRect, label);
position.y += labelRect.height + EditorGUIUtility.standardVerticalSpacing;
position.height -= EditorGUIUtility.standardVerticalSpacing + labelRect.height;
// do some text input control using position rect
EditorGUI.EndProperty();

That said, is there any reason you cannot use the built-in TextAreaAttribute for this case?

The LocalizedText class can have multiple text entries for a varying amount of languages, and has to give a warning when the text becomes too long. Hence I used a custom property drawer for it.

I was running into this (in 2025) and I learned a few things that weren’t mentioned in the thread:

  1. EditorGUILayout ignores OnGUI’s Rect position parameter. What it does is make a new reserved rect below the one OnGUI provides.
  2. The hack that sets the property height to 0 hides the original (unused) reserved area that OnGUI’s rect parameter provides.
  3. EditorGUI.BeginProperty or EditorGUI.PropertyScope is important for both formatting the text correctly in your drawer and showing the blue bar on the left according to prefab override state. Without it, the drawer has no indicators for showing that the property is overridden. If you set the original rect to 0, you will hide the blue bar on the left unless you get the correct rect.

The solution I went with is just to do it the very old school way and only use the EditorGUI methods and manually calculating the rect offsets.

If your drawer uses multiple lines, the helpful getters are EditorGUIUtility.singleLineHeight for the default height of one line of an inspector property, and EditorGUIUtility.standardVerticalSpacing for the default spacing between inspector properties.


Correct formatting:

image
Using OnGUI’s rect, PropertyScope and EditorGUI methods, correctly shows the state of prefab override


Incorrect formatting:


Using PropertyScope (using OnGUI’s rect) but also EditorGUILayout (which ignores OnGUI’s rect)


Incorrect formatting:


No PropertyScope and using EditorGUILayout.


Incorrect formatting:

image
Override GetPropertyHeight to return 0. Using PropertyScope and EditorGUILayout. The text is correctly formatted but the blue indicator on the side is absent.


Why is this still relevant in the context of Unity 6-0 and Editor UI-Toolkit?:

By default, PropertyDrawers/PropertyAttribute Drawers don’t get drawn using the UI Elements/CreatePropertyGUI. I think it requires that the whole inspector of that object is also drawn using UI Toolkit, which isn’t default, and too much work to apply to every component where you just happen to want to use your custom PropertyAttribute.

Saying hi from 2026 here! I too had this issue with a custom PropertyDrawer for a custom PropertyAttribute I was making, and found out exactly what was going on after a LOT of struggle, so thought to share my end-all solution for future googlers!

As @Pharan really nicely shows in his last reply is how the formatting of the space changes depending on if you use the EditorGUI.BeginProperty() / EditorGUI.EndProperty() functions, and how EditorGUILayout functions create and reserve their own space in the GUI, creating the extra spacing.

For any kind of PropertyDrawer/DecoratorDrawer, you need to do 2 things, USE the GetPropertyHeight() override function, and then only use EditorGUI or GUI functions, adjusting their input position rect parameters around as you see fit.

Before I show an example of a correctly setup script, I just want to highlight the “hacky” advice given above, and why it is bad advice of which you should avoid:

If you try to use the a EditorGUILayout function, as previously mentioned, this adds the extra space required for those layouts underneath a seemingly empty line/space. This space above is the original reserved space for the PropertyDrawer, plus a bit of spacing before the next EditorGUILayout element is drawn, resulting in a space with a height that equals EditorGUIUtility.singleLineHeight (18 pixels) + EditorGUIUtility.standardVerticalSpacing (1 pixel).

If you try to set the GetPropertyHeight() override function’s return value to 0, that only changes the height of the previous reserved space (the by-default, 18 pixels), yet still the spacing between that GUI and the following produced by the EditorGUILayout’s function (the by-default 1 pixel) will remain, so you’ll notice an odd 1 pixel bumper space between the previous inspector GUI and this property. It’s really obvious in a list of properties like so:

Another erroneous solution I’ve seen passed around is to use the EditorGUILayout.GetControlRect() function to build the position rect for use in your EditorGUI & GUI functions. This does correctly generate a rect that matches the passed in desired height, but NOTE, it is a EditorGUILayout function! So it’ll build the space for it after the already reserved space!

~Now, the correct solution is as follows!~

Use the GetPropertyHeight() override function to setup the desired height of the PropertyDrawer’s total height. In my case I wanted to use the original height of the property, which you can get using the EditorGUI.GetPropertyHeight() function, passing in the property, and if you wish to includeChildren. This second parameters refers to if the SerailizedProperty has child properties, such as a custom class that’s marked as [System.Serializeable] and inside that class is SerializedProperties, such as a string Name, float size, or Vector3 Position. I personally always pass includeChildren as true!

This GetPropertyHeight() override function is called first, then the OnGUI override function is called, and so to save on computing the height of your desired property twice, you could save the output of the earlier called EditorGUI.GetPropertyHeight() into a private float field within the class for use in the OnGUI override function! Now that the height was computed, the passed in position rect of the OnGUI function will have the correct position.height set to match! Now any EditorGUI or GUI functions can use the position rect to size themselves properly within the PropertyDrawer’s height!

Here’s an example I have for a custom attribute that has the property as it was before in a column on the left, then a new button on a column on the right edge:

And here is the results in that same list from earlier, and in use by a custom Serializeable class with child serialized data, all correctly formatted and showing prefab override highlights:

I hope with helps someone in the future, and provides the relevant information to work out what’s going wrong with their script!