PropertyDrawer.OnGUI label parameter: contents changing, but not by me

It appears that calling EditorGUI.GetPropertyHeight is, somehow, adjusting the label I’m using in my custom PropertyDrawer.OnGUI function!

The label is passed into my property drawer by the framework. Does it then use and alter the contents of that reference when I call certain framework functions?! Isn’t that … well, confusing at best, a bug at worst? Is there some other reason/way this could occur?

Perhaps I am missing the point of the parameter?

Or perhaps I just missed that part of the documentation? (The only docs I found for the label parameter of PropertyDrawer.OnGUI is, in its entirety: “The label of this property.” )

So if I don’t want it to change without my explicitly doing so; I assume the workaround is to instantiate my own GUIContent instance in the property drawer, using the data from the one passed in. Is that a bad solution for some reason I don’t see?

Here is the sample code I used to confirm this behavior.

SomeAsset.cs

using UnityEngine;
using UnityEditor;
public class SomeAsset : ScriptableObject
{
    public int someData = 0;
    public string stringData = "default";
    [MenuItem("Example/CreateSomeAsset", false, 100)]
    static public void Create()
    {
        AssetDatabase.CreateAsset(ScriptableObject.CreateInstance<SomeAsset>(), "Assets/someAsset.asset");
    }    
}

AssetUser.cs

using UnityEngine;

public class AssetUser : MonoBehaviour {
    public SomeAsset theAsset;
}

editor\SomeAssetPropertyDrawer.cs

using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(SomeAsset),true)]
public class SomeAssetPropertyDrawer : PropertyDrawer {

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        Debug.Log("label start: " + label.text);
        
        EditorGUI.DropShadowLabel(position, GUIContent.none, GUI.skin.box);
        Debug.Log("label post DropShadowLabel: " + label.text);
        position.height = EditorGUIUtility.singleLineHeight;
        EditorGUI.ObjectField(position, label, property.objectReferenceValue, typeof(SomeAsset),false);
        position.y += position.height + EditorGUIUtility.standardVerticalSpacing; ;
        Debug.Log("label post ObjectField: " + label.text);
        if (property.objectReferenceValue == null) return;
        SerializedObject propObj = new SerializedObject(property.objectReferenceValue);
        SerializedProperty someDataProperty = propObj.FindProperty("someData");
        SerializedProperty stringDataProperty = propObj.FindProperty("stringData");
        EditorGUI.indentLevel++;

        position.height = EditorGUI.GetPropertyHeight(someDataProperty);
        Debug.Log("label post someDataProperty get height: " + label.text);
        EditorGUI.PropertyField(position,someDataProperty);
        position.y += position.height + EditorGUIUtility.standardVerticalSpacing;
        Debug.Log("label post someDataPropertyField: " + label.text);

        position.height = EditorGUI.GetPropertyHeight(stringDataProperty);
        Debug.Log("label post stringDataProperty get height: " + label.text);
        EditorGUI.PropertyField(position, stringDataProperty);
        position.y += position.height + EditorGUIUtility.standardVerticalSpacing;
        Debug.Log("label post stringDataPropertyField: " + label.text);

        EditorGUI.indentLevel--;
        position.height = EditorGUIUtility.singleLineHeight;
        label.text = "End of :" + label.text;
        EditorGUI.LabelField(position, label);
        Debug.Log("label end: " + label.text);
    }
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        if (property.objectReferenceValue == null) return 0;
        SerializedObject propObj = new SerializedObject(property.objectReferenceValue); 

        SerializedProperty someDataProperty = propObj.FindProperty("someData");
        SerializedProperty stringDataProperty = propObj.FindProperty("stringData");
        float height = 2*( EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing);
        height += EditorGUI.GetPropertyHeight(someDataProperty) + EditorGUIUtility.standardVerticalSpacing;
        height += EditorGUI.GetPropertyHeight(stringDataProperty) + EditorGUIUtility.standardVerticalSpacing;
      
        return height;
    }
}

Resultant drawn property: note label on the line with "end of: "

So if I don’t want it to change
without my explicitly doing so; I
assume the workaround is to
instantiate my own GUIContent instance
in the property drawer, using the data
from the one passed in.

Pretty much, yes. (Or to a static one, etc.)

Is that a bad solution for some reason
I don’t see?

The problem is that GUIContent is a class, and so each time you create a new one it is a heap allocation (and eventual garbage collection). Unity is doing an optimization here by reusing the same reference for labels that are procedurally populated based on e.g. a property’s name.

However you decide to deal with, do keep in mind that your PropertyDrawer instance is likely to also be reused (it it appears for e.g., elements in an array).