LTS 2022.3.2f1 - PropertyField does not resolve correct type when using [SerializeReference]

Hey everyone,

I’m currently dealing with a rather interesting serialization situation that took me a while to figure.

I’m trying to create an Editor for managing custom properties of different value types. The property array is marked with [SerializeReference] in order to make sure that derived properties are being serialized correctly.

Let’s assume the following classes, I’ll try to keep everything as compact as possible:

[Serializable]
public abstract class BaseProperty
{
    [SerializeField]
    public string Name;
}
[Serializable]
public class BoolProperty : BaseProperty
{
    [SerializeField]
    public bool Value;
}

public class MyScript: MonoBehaviour
{
    [SerializeReference] // Derived classes should be serialized correctly with this
    public BaseProperty[] Properties; // Lets assume it only contains BoolProperty instances
}

And their respective Editor/PropertyDrawer classes:

[CustomPropertyDrawer(typeof(BaseProperty), true)]
public class BasePropertyPropertyDrawer : PropertyDrawer
{
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        // Associated inspector elements...

        // This part never runs after calling serializedObject.ApplyModifiedProperties()
    }
}

[CustomEditor(typeof(MyScript))]
public class MyScriptEditor : Editor
{
    private VisualElement _propertyContainer;

    public override VisualElement CreateInspectorGUI()
    {
        VisualElement container = new();

        _propertyContainer = new();
        container.Add(_propertyContainer);

        UpdatePropertyFields(); // This call works like a charm, everything is rendered correctly
        CreateProperty<BoolProperty>(); // New property is added successfully
        UpdatePropertyFields(); // All Recreated elements appear empty, serialization breaks
   
        return container;
    }

    private void UpdatePropertyFields()
    {
        _propertyContainer.Clear();

        using SerializedProperty serializedProperties = GetSerializedPropertiesArray();
        int length = serializedProperties.arraySize;
        for (int i = 0; i < length; i++)
        {
            using SerializedProperty property = serializedProperties.GetArrayElementAtIndex(i);
            PropertyField propertyField = new(property);
            _propertyContainer.Add(propertyField);
        }
    }

    private void CreateProperty<T>()
        where T : BaseProperty, new()
    {
        serializedObject.Update();

        // Extend properties array
        using SerializedProperty serializedProperties = GetSerializedPropertiesArray();
        serializedProperties.arraySize++;

        // Create new property and apply changes
        using SerializedProperty property = serializedProperties.GetArrayElementAtIndex(serializedProperties.arraySize - 1);
        property.managedReferenceValue = new T();
        serializedObject.ApplyModifiedProperties();
    }

    private SerializedProperty GetSerializedPropertiesArray()
        => serializedObject.FindProperty("Properties");
}

Everything works nicely, up to the point where I try to manually add a new property.
After successfully creating and adding the new BoolProperty and calling serializedObject.ApplyModifiedProperties(), the associated PropertyField fails to resolve the correct type.

Remarks:

  • The issue only happens after manually editing the serializedObject. Running UpdatePropertyFields multiple times without editing the target seems to be working just fine.
  • I have verified that the new property is correctly being added to the MonoBehaviour
  • I’m using Unity 2022.3.2f1

Does anyone have any idea on how to resolve or work around this issue?
Any advice will be greatly appreciated.

Many thanks in advance, looking forward to your answers!

TL;DR Creating a PropertyField out of a newly created derived object stored in a [SerializeReference] array of base classes, after calling serializedObject.ApplyModifiedProperties(), breaks.

Bump. Any updates from the community experts?