Exception when iterating through a serializedproperty sub elements in the list

Hi,
I’m trying to display a list of objects using UI Tookit with a custom display based on PeropertyField.
My main UI (in a class called ScenarioEditorSettingsProvider) has a list that I use to display the elements :

            SerializedObject serializedInputSettings = new(ScenarioEditorSettingsProfiles.instance);
            SerializedProperty defaultProfilesProperty = serializedInputSettings.FindProperty(nameof(ScenarioEditorSettingsProfiles.DefaultProfiles));

            rootElement.Q<ListView>("BaseProfiles").itemsSource = ScenarioEditorSettingsProfiles.instance.DefaultProfiles;
            rootElement.Q<ListView>("BaseProfiles").makeItem = () => new PropertyField();
            rootElement.Q<ListView>("BaseProfiles").bindItem = (e, i) =>
            {
                (e as PropertyField).BindProperty(defaultProfilesProperty.GetArrayElementAtIndex(i));
            };

So far so good. Now, I want to change the display of my class using a custom property drawer.

[CustomPropertyDrawer(typeof(DefaulScenarioEditorSettingsProfile))]
    public class MyCustomProfileDrawer : PropertyDrawer
    {
        public override VisualElement CreatePropertyGUI(SerializedProperty property)
        {
            // Create property container element.
            VisualElement container = new GroupBox();

            System.Collections.IEnumerator propertyEnum = property.GetEnumerator();
            while (propertyEnum.MoveNext())
            {
                SerializedProperty serializedProperty = propertyEnum.Current as SerializedProperty;
                if (serializedProperty.name == nameof(ScenarioEditorSettingsProfile.Name))
                    continue;

                PropertyField propertyField = new();
                propertyField.BindProperty(serializedProperty);
                propertyField.SetEnabled(false);
                container.Add(propertyField);
            }
            return container;
        }

    }

The code works Except for the last element of my list of objects (Meaning, the last element in “defaultProfilesProperty.GetArrayElementAtIndex(i)”). The last element always fails to display with the following in the console :

InvalidOperationException: The operation is not possible when moved past all properties (Next returned false)
UnityEditor.SerializedProperty.Verify (UnityEditor.SerializedProperty+VerifyFlags verifyFlags) (at <5092d70d16a64dd9a555dd50f38aead0>:0)
UnityEditor.SerializedProperty.FindPropertyRelativeInternal (System.String propertyPath) (at <5092d70d16a64dd9a555dd50f38aead0>:0)
UnityEditor.SerializedProperty.FindPropertyRelative (System.String relativePropertyPath) (at <5092d70d16a64dd9a555dd50f38aead0>:0)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.BindPropertyRelative (UnityEngine.UIElements.IBindable field, UnityEditor.SerializedProperty parentProperty) (at <963b7b516af945bcb7d30875c64e2e07>:0)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.BindTree (UnityEngine.UIElements.VisualElement element, UnityEditor.SerializedProperty parentProperty) (at <963b7b516af945bcb7d30875c64e2e07>:0)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.BindTree (UnityEngine.UIElements.VisualElement element, UnityEditor.SerializedProperty parentProperty) (at <963b7b516af945bcb7d30875c64e2e07>:0)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.BindTree (UnityEngine.UIElements.VisualElement element, UnityEditor.SerializedProperty parentProperty) (at <963b7b516af945bcb7d30875c64e2e07>:0)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.ContinueBinding (UnityEngine.UIElements.VisualElement element, UnityEditor.SerializedProperty parentProperty) (at <963b7b516af945bcb7d30875c64e2e07>:0)
UnityEditor.UIElements.Bindings.SerializedObjectBindingContext.Bind (UnityEngine.UIElements.VisualElement element) (at <963b7b516af945bcb7d30875c64e2e07>:0)
UnityEditor.UIElements.Bindings.DefaultSerializedObjectBindingImplementation.BindProperty (UnityEngine.UIElements.IBindable field, UnityEditor.SerializedProperty property) (at <963b7b516af945bcb7d30875c64e2e07>:0)
UnityEditor.UIElements.BindingExtensions.BindProperty (UnityEngine.UIElements.IBindable field, UnityEditor.SerializedProperty property) (at <963b7b516af945bcb7d30875c64e2e07>:0)
Xareus.Unity.Editor.Scenarios.Settings.ScenarioEditorSettingsProvider+<>c__DisplayClass4_0.b__1 (UnityEngine.UIElements.VisualElement e, System.Int32 i) (at Packages/fr.insa.xareus/Editor/Scenarios/Settings/ScenarioEditorSettingsProvider.cs:69)
UnityEngine.UIElements.CollectionViewController.BindItem (UnityEngine.UIElements.VisualElement element, System.Int32 index) (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEngine.UIElements.CollectionViewController.InvokeBindItem (UnityEngine.UIElements.ReusableCollectionItem reusableItem, System.Int32 index) (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEngine.UIElements.ListViewController.InvokeBindItem (UnityEngine.UIElements.ReusableCollectionItem reusableItem, System.Int32 index) (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEngine.UIElements.VerticalVirtualizationController1[T].Setup (T recycledItem, System.Int32 newIndex) (at <1aaa12d3c5d64d42836d89caff78b60b>:0) UnityEngine.UIElements.DynamicHeightVirtualizationController1[T].Fill () (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEngine.UIElements.VisualElement+SimpleScheduledItem.PerformTimerUpdate (UnityEngine.UIElements.TimerState state) (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEngine.UIElements.TimerEventScheduler.UpdateScheduledEvents () (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEngine.UIElements.UIElementsUtility.UnityEngine.UIElements.IUIElementsUtility.UpdateSchedulers () (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEngine.UIElements.UIEventRegistration.UpdateSchedulers () (at <1aaa12d3c5d64d42836d89caff78b60b>:0)
UnityEditor.RetainedMode.UpdateSchedulers () (at <963b7b516af945bcb7d30875c64e2e07>:0)

I tried different ways of displaying this data but none worked

Bug confirmed by Unity : IN-41224
https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-41224

2 Likes

Thank you for reporting it!

The solution to this issue can be found here : Unity Issue Tracker - The last element of an array is not displayed when using a ListView of elements with a custom PropertyDrawer

TLDR: Make a copy() of the serialized property before iterating on it because it is already an iterator