Unity crashes after reordering SerializeReference object in a List

Hey,
I’m trying to make a custom inspector for a script. One of the important elements inside the inspector is a list of commands. This list gets updated based on another list and so it’s okay to just list out the commands without the need of a reorderable list. The problem occurs inside each command, as each one needs to have a reorderable list of actions. Each action has a pretty complicated structure as I need to setup the conditions, the unity event results etc. Because the structure is so complicated, I decided to do it myself and to do a custom ReorderableList. Here’s how it looks like. There is one command called default and one action I added:

My solution works except for one thing: when I actually try to reorder the elements, the entire Unity software crashes:

This window shows up and after about a minute and a half Unity closes itself and a Unity Bug Reporter window shows up.

By detecting when I let go of the left mouse button, I was able to debug the code when I let go of the element that I’m trying to reorder and I found out where exactly the program crashes but I’m not able to find a reason for it. Here’s the code of the Unity editor as well as the runtime script itself and afterwards I describe where it fails:

using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditorInternal;
using System;

[CustomEditor(typeof(Interactable))]
public class InteractableEditor : Editor
{
    Interactable m_Target;
    SerializedProperty itemProperty;
    SerializedProperty onCursorEnterProperty;
    SerializedProperty onCursorExitProperty;
    SerializedProperty commandsProperty;

    readonly Dictionary<int, ReorderableList> actionLists = new();
    readonly List<bool> foldouts = new(); // Stores open/close state for each Name
    bool foldCommands = true; // Toggle visibility of the entire "Commands" section
    bool foldAll = true; // Toggle all Commands at once

    protected virtual void OnEnable()
    {
        m_Target = (Interactable)target;
        if (m_Target == null)
            return;

        itemProperty = serializedObject.FindProperty("Item");
        onCursorEnterProperty = serializedObject.FindProperty("OnCursorEnter");
        onCursorExitProperty = serializedObject.FindProperty("OnCursorExit");
        commandsProperty = serializedObject.FindProperty("Commands");

        // Initialize foldouts list to match the number of Commands
        for (int i = 0; i < commandsProperty.arraySize; i++)
        {
            foldouts.Add(false); // Default: not expanded
        }

        UpdateCommands();
        //SetCommands();
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        // Get the target object
        m_Target = (Interactable)target;
        if (m_Target == null)
            return;

        if (Event.current.type == EventType.MouseUp)
        {
            if (Event.current.button == 0)
                Debug.Log("Left mouse released.");  // for detecting crash
        }

        // Draw other property fields in the Inspector
        EditorGUILayout.PropertyField(itemProperty);

        UpdateCommands();
        SetCommands();

        EditorGUILayout.PropertyField(onCursorEnterProperty);
        EditorGUILayout.PropertyField(onCursorExitProperty);

        serializedObject.ApplyModifiedProperties();
    }

    /// <summary>
    /// Sets up the Commands property objectField.
    /// </summary>
    protected void SetCommands()
    {
        foldCommands = EditorGUILayout.Foldout(foldCommands, "Commands", true);
        EditorGUILayout.BeginVertical("box");

        if (foldCommands)
        {
            if (commandsProperty.arraySize > 0)
            {
                GUILayout.Space(2);
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                if (GUILayout.Button(foldAll ? "Collapse All" : "Expand All", GUILayout.Width(EditorGUIUtility.currentViewWidth - 50)))
                {
                    foldAll = !foldAll;
                    for (int i = 0; i < foldouts.Count; i++) foldouts[i] = foldAll;
                }
                GUILayout.FlexibleSpace();
                EditorGUILayout.EndHorizontal();
                GUILayout.Space(2);
            }

            if (commandsProperty.arraySize == 0)
                EditorGUILayout.HelpBox("No commands available.", MessageType.Info);

            for (int i = 0; i < commandsProperty.arraySize; i++)
            {
                SerializedProperty commandElementProp = commandsProperty.GetArrayElementAtIndex(i);
                SerializedProperty itemProp = commandElementProp.FindPropertyRelative("data");
                SerializedProperty actionsProp = commandElementProp.FindPropertyRelative("actions");

                EditorGUI.indentLevel++;
                foldouts[i] = EditorGUILayout.Foldout(foldouts[i], itemProp.FindPropertyRelative("name").stringValue, true);

                if (foldouts[i])
                {
                    EditorGUILayout.BeginVertical("box");

                    if (!actionLists.ContainsKey(i))
                    {
                        actionLists[i] = CreateReorderableActionList(actionsProp);
                    }

                    actionLists[i].DoLayoutList();

                    EditorGUILayout.EndVertical();
                }

                EditorGUI.indentLevel--;
            }
        }

        EditorGUILayout.EndVertical();
    }

    private ReorderableList CreateReorderableActionList(SerializedProperty actionsProp)
    {
        var list = new ReorderableList(actionsProp.serializedObject, actionsProp, true, true, true, true)
        {
            drawHeaderCallback = (Rect rect) =>
            {
                EditorGUI.LabelField(rect, "Actions");
            },

            drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) =>
            {
                SerializedProperty actionProp = actionsProp.GetArrayElementAtIndex(index);
                SerializedProperty moveCloserProp = actionProp.FindPropertyRelative("moveCloser");
                SerializedProperty conditionsProp = actionProp.FindPropertyRelative("conditions");
                SerializedProperty previousInteractablesProp = actionProp.FindPropertyRelative("previousInteractables");
                SerializedProperty leftActionProp = actionProp.FindPropertyRelative("leftMouseButtonActions");
                SerializedProperty rightActionProp = actionProp.FindPropertyRelative("rightMouseButtonActions");

                EditorGUI.BeginProperty(rect, GUIContent.none, actionProp);

                Rect r = rect;
                r.y += EditorGUIUtility.singleLineHeight + 4f;  // Move content down
                r.height = EditorGUIUtility.singleLineHeight;

                float indent = 15f; // Optional horizontal shift to indent a bit
                r.x += indent;
                r.width -= indent;

                EditorGUI.PropertyField(r, previousInteractablesProp, new GUIContent("Previous Interactables"), true);
                r.y += EditorGUI.GetPropertyHeight(previousInteractablesProp, true) + 2f;

                EditorGUI.PropertyField(r, conditionsProp, new GUIContent("Conditions"), true);
                r.y += EditorGUI.GetPropertyHeight(conditionsProp, true) + 2f;

                EditorGUI.LabelField(r, "Add condition");
                r.y += 5f;
                // Add buttons to add conditions (inside each action's list)
                Rect buttonRect = r;
                buttonRect.y += r.height;
                buttonRect.width /= 4f; // Adjust width for buttons

                if (GUI.Button(buttonRect, "Bool"))
                {
                    AddConditionToAction(conditionsProp, typeof(BoolCondition));
                }

                buttonRect.x += buttonRect.width;
                if (GUI.Button(buttonRect, "String"))
                {
                    AddConditionToAction(conditionsProp, typeof(StringCondition));
                }

                buttonRect.x += buttonRect.width;
                if (GUI.Button(buttonRect, "Int"))
                {
                    AddConditionToAction(conditionsProp, typeof(IntCondition));
                }

                buttonRect.x += buttonRect.width;
                if (GUI.Button(buttonRect, "Float"))
                {
                    AddConditionToAction(conditionsProp, typeof(FloatCondition));
                }

                r.y += buttonRect.height * 3 + 4f;

                EditorGUI.PropertyField(r, moveCloserProp, new GUIContent("Move closer?"));
                r.y += EditorGUIUtility.singleLineHeight + 4f;

                // Left Mouse Button Actions
                EditorGUI.PropertyField(r, leftActionProp, new GUIContent("Left Mouse Actions"), true);
                r.y += EditorGUI.GetPropertyHeight(leftActionProp, true) + 2f;

                // Right Mouse Button Actions
                EditorGUI.PropertyField(r, rightActionProp, new GUIContent("Right Mouse Actions"), true);
                r.y += EditorGUI.GetPropertyHeight(rightActionProp, true) + 2f;

                EditorGUI.EndProperty();
            },

            elementHeightCallback = (int index) =>
            {
                SerializedProperty actionProp = actionsProp.GetArrayElementAtIndex(index);
                float height = EditorGUIUtility.singleLineHeight + 2;
                height += EditorGUI.GetPropertyHeight(actionProp.FindPropertyRelative("leftMouseButtonActions"));
                height += EditorGUI.GetPropertyHeight(actionProp.FindPropertyRelative("rightMouseButtonActions"));
                height += EditorGUI.GetPropertyHeight(actionProp.FindPropertyRelative("conditions"));
                height += EditorGUI.GetPropertyHeight(actionProp.FindPropertyRelative("previousInteractables"));
                height += EditorGUI.GetPropertyHeight(actionProp.FindPropertyRelative("moveCloser"));
                return height + 80; // add some padding
            }
        };

        return list;
    }

    private void AddConditionToAction(SerializedProperty conditionsProp, Type conditionType)
    {
        var newCondition = Activator.CreateInstance(conditionType);
        conditionsProp.arraySize++;
        conditionsProp.GetArrayElementAtIndex(conditionsProp.arraySize - 1).managedReferenceValue = newCondition;
    }

    /// <summary>
    /// Updates the Commands property according to GameManager.Instance.Commands.
    /// </summary>
    protected void UpdateCommands()
    {
        // Retrieve Name list from the GameManager
        var gmCommands = new List<CommandData>();
        if (GameManager.Instance == null)
            gmCommands = FindObjectOfType<GameManager>().Commands;
        else
            gmCommands = GameManager.Instance.Commands;

        var updatedCommands = new List<CommandAction>();
        var updatedFoldouts = new List<bool>();

        while (foldouts.Count < m_Target.Commands.Count)
        {
            foldouts.Add(true);
        }

        // Handles new Commands in GM
        foreach (var gm_c in gmCommands)
        {
            // Preserve existing Commands if they match a Name 
            var existingCommand = m_Target.Commands.Find(c => c.data.guid == gm_c.guid);
            if (existingCommand != null)
            {
                existingCommand.data.name = gm_c.name;
                updatedCommands.Add(existingCommand); // Keep existing Name
                updatedFoldouts.Add(foldouts[m_Target.Commands.IndexOf(existingCommand)]);
            }
            else
            {
                updatedCommands.Add(new CommandAction(gm_c)); // Create new Name
                updatedFoldouts.Add(false);
            }
        }

        // Update EnvironmentObject Commands and mark object as modified
        m_Target.Commands = updatedCommands;
    }
}

and now the script for Interactable:

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;


public class Interactable : MonoBehaviour
{
    public Item Item;
    
    public UnityEvent OnCursorEnter;
    public UnityEvent OnCursorExit;
    public List<CommandAction> Commands = new();
}


/// <summary>
/// Defines the Name and the action of a Name.
/// </summary>
[System.Serializable]
public class CommandAction
{
    [HideInInspector] public CommandData data;
    public List<Action> actions;

    public CommandAction(CommandData item)
    {
        data = item;
    }
}

[System.Serializable]
public class Action
{
    public List<Interactable> previousInteractables; 
    [SerializeReference] public List<Condition> conditions;
    public bool moveCloser;

    public UnityEvent leftMouseButtonActions;
    public UnityEvent rightMouseButtonActions;

    public UnityEvent CallLeftOrRightEvent(bool left)
    {
        return left ? leftMouseButtonActions : rightMouseButtonActions;
    }
}

So the place where it crashes is the line in SetCommands() method:
actionLists[i].DoLayoutList();

At first, it runs normally: the code in drawElementCallback in CreateReorderableActionList(...) gets called as many times as there are elements in the ReorderableList. Finally after the last element runs the line EditorGUI.EndProperty();, Unity crashes as described above. There is no exception as far as I can see, no warning, just a crash.

I also noticed that when I unfold and show all the reorderable lists (meaning actions) in editor, the inspector gets slower the more actions there are. The scrolling becomes pretty laggy and it might have something to do with the crash.

I feel like I’m doing something wrong with the ReorderableList but I don’t know what. I tried to follow tutorials but my custom list is pretty complex and I might’ve done something very wrong. I haven’t had much experience with ReorderableList before trying this thing.

I’m looking for help with either:

  1. Showing me how to fix this mess while keeping the ReorderableList.
  2. Showing me how to set it up in another way so that I can achieve a similar effect as right now.

If there’s anything I failed to explain properly, let me know. Any help would be appreciated!

Anything useful near the end of the editor.log after the crash? If it’s a StackoverflowException this will only get logged, or you can catch it by globally enabling to break on StackoverflowException in the IDE. You could also step up to that particular line, then enable to break on ALL exceptions in the IDE to catch whatever might get thrown in there.

FWIW Unity recommends to use UI Toolkit for editor tooling.

And even though I don’t know what the use-case is, just judging by the UI layout something of this complexity ought to be its own EditorWindow. I mean just look at how far you had to scroll down in the Inspector to even get to that part of your UI.

Also, how complex is “complex” in measurable terms? A few dozen entries in a list, okay. But when you get to hundreds of UI elements in a single editor it’s going to start dragging down the editor. More so since you are using IMGUI, UI Toolkit is a lot more efficient.

Your data seems to have an infinite serialization loop. Interactable has a list of CommandAction, which has a list of Action, which by-value serializes a list of more Interactables, potentially the cause of the crash. previousInteractables should be serialized by-reference with [SerializeReference] as well.

Not sure if this is the cause of the crash, but still an issue that should be fixed.

Thank you, I feel like the inspector is running more smoothly thanks to that. Unfortunately, it still crashes but thanks for your help!

Edit: Not sure about the “running more smoothly” part, I realized that it’s more laggy when I debug it which is to be expected I guess. Anyway still trying to find the problem

Thank you for your answer.
First about the complexity part: each object that uses this script is expected to have at least one of these actions but realistically not more than about 3 or 5. For context, I’m attempting to make a small-ish framework for 2D point-and-click adventure games and this script Interactable and specifically the actions list is supposed to keep the info about the logic of what happens under certain conditions. Other scripts later handle the logic. So maybe a certain object is not pickable currently but under different conditions it is. I don’t expect there to be many many many actions.

So back to the crash: I wasn’t able to catch any exception in the IDE but I looked into the Editor.log like you suggested and here’s the result (hopefully it’s okay to share it):

(Filename: Assets/Scripts/InventorySystem/Editor/InteractableEditor.cs Line: 54)

Left mouse released.
UnityEngine.StackTraceUtility:ExtractStackTrace ()
UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
UnityEngine.Logger:Log (UnityEngine.LogType,object)
UnityEngine.Debug:Log (object)
InteractableEditor:OnInspectorGUI () (at Assets/Scripts/InventorySystem/Editor/InteractableEditor.cs:54)
EnvironmentObjectEditor:OnInspectorGUI () (at Assets/Scripts/InventorySystem/Editor/EnvironmentObjectEditor.cs:48)
UnityEditor.UIElements.InspectorElement/<>c__DisplayClass72_0:<CreateInspectorElementUsingIMGUI>b__0 ()
UnityEngine.UIElements.IMGUIContainer:DoOnGUI (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,bool,UnityEngine.Rect,System.Action,bool)
UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,System.Action,bool)
UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,System.Action,bool)
UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,bool)
UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUIRaw (UnityEngine.UIElements.EventBase,bool,bool)
UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUI (UnityEngine.UIElements.EventBase,bool,bool)
UnityEngine.UIElements.IMGUIContainer:ProcessEvent (UnityEngine.UIElements.EventBase)
UnityEngine.UIElements.CallbackEventHandler:HandleEvent (UnityEngine.UIElements.EventBase)
UnityEngine.UIElements.CallbackEventHandler:HandleEventAtCurrentTargetAndPhase (UnityEngine.UIElements.EventBase)
UnityEngine.UIElements.CallbackEventHandler:HandleEventAtTargetPhase (UnityEngine.UIElements.EventBase)
UnityEngine.UIElements.MouseCaptureDispatchingStrategy:DispatchEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel)
UnityEngine.UIElements.EventDispatcher:ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel,bool)
UnityEngine.UIElements.EventDispatcher:ProcessEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel)
UnityEngine.UIElements.EventDispatcher:ProcessEventQueue ()
UnityEngine.UIElements.EventDispatcher:OpenGate ()
UnityEngine.UIElements.EventDispatcherGate:Dispose ()
UnityEngine.UIElements.EventDispatcher:ProcessEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel)
UnityEngine.UIElements.EventDispatcher:Dispatch (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel,UnityEngine.UIElements.DispatchMode)
UnityEngine.UIElements.BaseVisualElementPanel:SendEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.DispatchMode)
UnityEngine.UIElements.UIElementsUtility:DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel)
UnityEngine.UIElements.UIElementsUtility:UnityEngine.UIElements.IUIElementsUtility.ProcessEvent (int,intptr,bool&)
UnityEngine.UIElements.UIEventRegistration:ProcessEvent (int,intptr)
UnityEngine.UIElements.UIEventRegistration/<>c:<.cctor>b__1_2 (int,intptr)
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

(Filename: Assets/Scripts/InventorySystem/Editor/InteractableEditor.cs Line: 54)


=================================================================
	Native Crash Reporting
=================================================================
Got a UNKNOWN while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

=================================================================
	Managed Stacktrace:
=================================================================
	  at <unknown> <0xffffffff>
	  at UnityEditor.SerializedProperty:MoveArrayElementInternal <0x00156>
	  at UnityEditor.SerializedProperty:MoveArrayElement <0x000f2>
	  at UnityEditorInternal.ReorderableList:DoDraggingAndSelection <0x05432>
	  at UnityEditorInternal.ReorderableList:DoListElements <0x05312>
	  at UnityEditorInternal.ReorderableList:DoLayoutList <0x00792>
	  at InteractableEditor:SetCommands <0x00ec2>
	  at InteractableEditor:OnInspectorGUI <0x0045a>
	  at EnvironmentObjectEditor:OnInspectorGUI <0x0024a>
	  at <>c__DisplayClass72_0:<CreateInspectorElementUsingIMGUI>b__0 <0x018ff>
	  at UnityEngine.UIElements.IMGUIContainer:DoOnGUI <0x01df0>
	  at UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent <0x00b92>
	  at UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent <0x0023a>
	  at UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent <0x000e2>
	  at UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUIRaw <0x0029a>
	  at UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUI <0x00f72>
	  at UnityEngine.UIElements.IMGUIContainer:ProcessEvent <0x000f2>
	  at UnityEngine.UIElements.CallbackEventHandler:HandleEvent <0x00a92>
	  at UnityEngine.UIElements.CallbackEventHandler:HandleEventAtCurrentTargetAndPhase <0x0008b>
	  at UnityEngine.UIElements.CallbackEventHandler:HandleEventAtTargetPhase <0x0016a>
	  at UnityEngine.UIElements.MouseCaptureDispatchingStrategy:DispatchEvent <0x01212>
	  at UnityEngine.UIElements.EventDispatcher:ApplyDispatchingStrategies <0x002b5>
	  at UnityEngine.UIElements.EventDispatcher:ProcessEvent <0x0046a>
	  at UnityEngine.UIElements.EventDispatcher:ProcessEventQueue <0x0035a>
	  at UnityEngine.UIElements.EventDispatcher:OpenGate <0x001ea>
	  at UnityEngine.UIElements.EventDispatcherGate:Dispose <0x0008a>
	  at UnityEngine.UIElements.EventDispatcher:ProcessEvent <0x01442>
	  at UnityEngine.UIElements.EventDispatcher:Dispatch <0x0043a>
	  at UnityEngine.UIElements.BaseVisualElementPanel:SendEvent <0x0017a>
	  at UnityEngine.UIElements.UIElementsUtility:DoDispatch <0x00c62>
	  at UnityEngine.UIElements.UIElementsUtility:UnityEngine.UIElements.IUIElementsUtility.ProcessEvent <0x002c2>
	  at UnityEngine.UIElements.UIEventRegistration:ProcessEvent <0x00233>
	  at <>c:<.cctor>b__1_2 <0x0009a>
	  at UnityEngine.GUIUtility:ProcessEvent <0x00114>
	  at <Module>:runtime_invoke_void_int_intptr_intptr& <0x001b5>
=================================================================
Received signal SIGSEGV
Obtained 67 stack frames
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac197787 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac197787 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac1977e7 (Unity) WalkTypeTreeComplete<`SerializedObjectTypeTreeWalk::ContainsManagedReferences'::`2'::IsManagedReferenceVisitor>
0x00007ff7ac199ada (Unity) SerializedObjectTypeTreeWalk::ContainsManagedReferences
0x00007ff7ac1d7618 (Unity) SerializedProperty::MoveArrayElement
0x00007ff7aa9869a9 (Unity) SerializedProperty_CUSTOM_MoveArrayElementInternal
0x000001f577f7df97 (Mono JIT Code) (wrapper managed-to-native) UnityEditor.SerializedProperty:MoveArrayElementInternal (UnityEditor.SerializedProperty,int,int)
0x000001f577f7dd63 (Mono JIT Code) UnityEditor.SerializedProperty:MoveArrayElement (int,int)
0x000001f577f478b3 (Mono JIT Code) UnityEditorInternal.ReorderableList:DoDraggingAndSelection (UnityEngine.Rect)
0x000001f577f17153 (Mono JIT Code) UnityEditorInternal.ReorderableList:DoListElements (UnityEngine.Rect,UnityEngine.Rect)
0x000001f577f3a863 (Mono JIT Code) UnityEditorInternal.ReorderableList:DoLayoutList ()
0x000001f577f083c3 (Mono JIT Code) InteractableEditor:SetCommands () (at C:/Users/path-to-project/Assets/Scripts/InventorySystem/Editor/InteractableEditor.cs:115)
0x000001f577f072db (Mono JIT Code) InteractableEditor:OnInspectorGUI () (at C:/Users/path-to-project/Assets/Scripts/InventorySystem/Editor/InteractableEditor.cs:61)
0x000001f577f0699b (Mono JIT Code) EnvironmentObjectEditor:OnInspectorGUI () (at C:/Users/path-to project/Assets/Scripts/InventorySystem/Editor/EnvironmentObjectEditor.cs:48)
0x000001f577dade20 (Mono JIT Code) UnityEditor.UIElements.InspectorElement/<>c__DisplayClass72_0:<CreateInspectorElementUsingIMGUI>b__0 ()
0x000001f42f046db1 (Mono JIT Code) UnityEngine.UIElements.IMGUIContainer:DoOnGUI (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,bool,UnityEngine.Rect,System.Action,bool)
0x000001f42f2ebae3 (Mono JIT Code) UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,UnityEngine.Matrix4x4,UnityEngine.Rect,System.Action,bool)
0x000001f43677c5bb (Mono JIT Code) UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,System.Action,bool)
0x000001f43677c2c3 (Mono JIT Code) UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent (UnityEngine.Event,bool)
0x000001f43677a66b (Mono JIT Code) UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUIRaw (UnityEngine.UIElements.EventBase,bool,bool)
0x000001f436772d73 (Mono JIT Code) UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUI (UnityEngine.UIElements.EventBase,bool,bool)
0x000001f56b3fadf3 (Mono JIT Code) UnityEngine.UIElements.IMGUIContainer:ProcessEvent (UnityEngine.UIElements.EventBase)
0x000001f56b3f9e53 (Mono JIT Code) UnityEngine.UIElements.CallbackEventHandler:HandleEvent (UnityEngine.UIElements.EventBase)
0x000001f56b3f92fc (Mono JIT Code) UnityEngine.UIElements.CallbackEventHandler:HandleEventAtCurrentTargetAndPhase (UnityEngine.UIElements.EventBase)
0x000001f56b3f87cb (Mono JIT Code) UnityEngine.UIElements.CallbackEventHandler:HandleEventAtTargetPhase (UnityEngine.UIElements.EventBase)
0x000001f28992bd03 (Mono JIT Code) UnityEngine.UIElements.MouseCaptureDispatchingStrategy:DispatchEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel)
0x000001f56d5f4b26 (Mono JIT Code) UnityEngine.UIElements.EventDispatcher:ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel,bool)
0x000001f56d5f33bb (Mono JIT Code) UnityEngine.UIElements.EventDispatcher:ProcessEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel)
0x000001f56b3935cb (Mono JIT Code) UnityEngine.UIElements.EventDispatcher:ProcessEventQueue ()
0x000001f56b3931ab (Mono JIT Code) UnityEngine.UIElements.EventDispatcher:OpenGate ()
0x000001f56b392f2b (Mono JIT Code) UnityEngine.UIElements.EventDispatcherGate:Dispose ()
0x000001f56d5f4393 (Mono JIT Code) UnityEngine.UIElements.EventDispatcher:ProcessEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel)
0x000001f56d5f249b (Mono JIT Code) UnityEngine.UIElements.EventDispatcher:Dispatch (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.IPanel,UnityEngine.UIElements.DispatchMode)
0x000001f56d5f1fab (Mono JIT Code) UnityEngine.UIElements.BaseVisualElementPanel:SendEvent (UnityEngine.UIElements.EventBase,UnityEngine.UIElements.DispatchMode)
0x000001f57836a6d3 (Mono JIT Code) UnityEngine.UIElements.UIElementsUtility:DoDispatch (UnityEngine.UIElements.BaseVisualElementPanel)
0x000001f578369633 (Mono JIT Code) UnityEngine.UIElements.UIElementsUtility:UnityEngine.UIElements.IUIElementsUtility.ProcessEvent (int,intptr,bool&)
0x000001f578368fa4 (Mono JIT Code) UnityEngine.UIElements.UIEventRegistration:ProcessEvent (int,intptr)
0x000001f578368c9b (Mono JIT Code) UnityEngine.UIElements.UIEventRegistration/<>c:<.cctor>b__1_2 (int,intptr)
0x000001f578368745 (Mono JIT Code) UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)
0x000001f578368986 (Mono JIT Code) (wrapper runtime-invoke) <Module>:runtime_invoke_void_int_intptr_intptr& (object,intptr,intptr,intptr)
0x00007ff8b0e5e274 (mono-2.0-bdwgc) mono_jit_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/mini/mini-runtime.c:3445)
0x00007ff8b0d9eb74 (mono-2.0-bdwgc) do_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/metadata/object.c:3066)
0x00007ff8b0d9ed0c (mono-2.0-bdwgc) mono_runtime_invoke (at C:/build/output/Unity-Technologies/mono/mono/metadata/object.c:3113)
0x00007ff7ab1b9d14 (Unity) scripting_method_invoke
0x00007ff7ab197e34 (Unity) ScriptingInvocation::Invoke
0x00007ff7ab192a85 (Unity) ScriptingInvocation::Invoke<void>
0x00007ff7ab2ed13a (Unity) Scripting::UnityEngine::GUIUtilityProxy::ProcessEvent
0x00007ff7abce0068 (Unity) GUIView::ProcessRetainedMode
0x00007ff7ac2aa6fe (Unity) GUIView::OnInputEvent
0x00007ff7abcdffb3 (Unity) GUIView::ProcessInputEventFromAPI
0x00007ff7abcdfe88 (Unity) GUIView::ProcessInputEvent
0x00007ff7ac2ab52e (Unity) GUIView::ProcessEventMessages
0x00007ff7ac2a52b5 (Unity) GUIView::GUIViewWndProc
0x00007ff951beb643 (USER32) CallWindowProcW
0x00007ff951be91cd (USER32) IsWindowUnicode
0x00007ff7ac27dff3 (Unity) MainMessageLoop
0x00007ff7ac2839d0 (Unity) WinMain
0x00007ff7ad667dbe (Unity) __scrt_common_main_seh
0x00007ff951ece8d7 (KERNEL32) BaseThreadInitThunk
0x00007ff9533114fc (ntdll) RtlUserThreadStart

It looks like the problem is when moving the elements around but not sure how to fix it…

Hmmm is perhaps one of the elements null or of the “wrong” type?

I couldn’t find DoLayoutList() in the documentation. Perhaps that’s not supported to be called from where you call it, or it may require setup.

I see, thank you for your answer! I’ll keep looking :slight_smile:

Hi, so I have an update: I was trying to do it another way and not overcomplicate it. So I decided to do it with regular old List, which I considered reliable and was hoping wouldn’t cause any problems. So here’s my setup:

public class ActionManager : MonoBehaviour
{
    public List<LabeledAction> actions = new();
}

[Serializable]
public class LabeledAction
{
    public string label;
    [HideInInspector]
    public Action action;

    public UnityEvent leftMouseButtonActions;
    public UnityEvent rightMouseButtonActions;
}

[Serializable]
public class Action
{
    public bool requireInteractables;
    public bool moveCloser;
    [SerializeField]
    public List<Item> previousInteractables = new();
    [SerializeReference] 
    public List<Condition> conditions = new();
}

[Serializable]
public abstract class Condition
{
    public abstract bool Check();
}

However, it turns out the same problem also occurred in this setup. I was pretty stumped and was trying different things. Finally, I realized when Unity would crash and when it wouldn’t: the culprit was [SerializeReference] at the conditions list: whenever I removed it, the reordering would run smoothly and when I used it, it would either lag for a second or it would crash Unity completely. Since the type Condition is abstract class and therefore I’m using polymorphism, it looks like I need to use [SerializeReference]. I was looking into [SerializeReference] a bit more closely and I encountered some bugs reported using it but nothing exactly same as my problem.

I also tried to copy this setup in a new project but it did not crash, so unfortunately it is hard to replicate the problem. That’s why I’m afraid this problem won’t be solved but I still hope someone might help me find a solution. Thank you and just to make this report complete, I’m adding error log from Editor.log:

=================================================================
	Native Crash Reporting
=================================================================
Got a UNKNOWN while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

=================================================================
	Managed Stacktrace:
=================================================================
	  at <unknown> <0xffffffff>
	  at UnityEditor.SerializedProperty:MoveArrayElementInternal <0x00156>
	  at UnityEditor.SerializedProperty:MoveArrayElement <0x000f2>
	  at UnityEditorInternal.ReorderableList:DoDraggingAndSelection <0x05432>
	  at UnityEditorInternal.ReorderableList:DoListElements <0x05312>
	  at UnityEditorInternal.ReorderableList:DoList <0x00912>
	  at UnityEditorInternal.ReorderableListWrapper:DrawChildren <0x01482>
	  at UnityEditorInternal.ReorderableListWrapper:Draw <0x01bfa>
	  at UnityEditor.PropertyHandler:OnGUI <0x0251a>
	  at UnityEditor.PropertyHandler:OnGUI <0x001da>
	  at UnityEditor.PropertyHandler:OnGUILayout <0x00532>
	  at UnityEditor.EditorGUILayout:PropertyField <0x000e2>
	  at UnityEditor.EditorGUILayout:PropertyField <0x0009a>
	  at UnityEditor.Editor:DoDrawDefaultInspector <0x00302>
	  at UnityEditor.Editor:DoDrawDefaultInspector <0x0019a>
	  at UnityEditor.Editor:DrawDefaultInspector <0x0008a>
	  at ActionManagerEditor:OnInspectorGUI <0x000b2>
	  at <>c__DisplayClass72_0:<CreateInspectorElementUsingIMGUI>b__0 <0x018ff>
	  at UnityEngine.UIElements.IMGUIContainer:DoOnGUI <0x01df0>
	  at UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent <0x00b92>
	  at UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent <0x0023a>
	  at UnityEngine.UIElements.IMGUIContainer:HandleIMGUIEvent <0x000e2>
	  at UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUIRaw <0x0029a>
	  at UnityEngine.UIElements.IMGUIContainer:SendEventToIMGUI <0x00f72>
	  at UnityEngine.UIElements.IMGUIContainer:ProcessEvent <0x000f2>
	  at UnityEngine.UIElements.CallbackEventHandler:HandleEvent <0x00a92>
	  at UnityEngine.UIElements.CallbackEventHandler:HandleEventAtCurrentTargetAndPhase <0x0008b>
	  at UnityEngine.UIElements.CallbackEventHandler:HandleEventAtTargetPhase <0x0016a>
	  at UnityEngine.UIElements.MouseCaptureDispatchingStrategy:DispatchEvent <0x01212>
	  at UnityEngine.UIElements.EventDispatcher:ApplyDispatchingStrategies <0x002b5>
	  at UnityEngine.UIElements.EventDispatcher:ProcessEvent <0x0046a>
	  at UnityEngine.UIElements.EventDispatcher:ProcessEventQueue <0x0035a>
	  at UnityEngine.UIElements.EventDispatcher:OpenGate <0x001ea>
	  at UnityEngine.UIElements.EventDispatcherGate:Dispose <0x0008a>
	  at UnityEngine.UIElements.EventDispatcher:ProcessEvent <0x01442>
	  at UnityEngine.UIElements.EventDispatcher:Dispatch <0x0043a>
	  at UnityEngine.UIElements.BaseVisualElementPanel:SendEvent <0x0017a>
	  at UnityEngine.UIElements.UIElementsUtility:DoDispatch <0x00c62>
	  at UnityEngine.UIElements.UIElementsUtility:UnityEngine.UIElements.IUIElementsUtility.ProcessEvent <0x002c2>
	  at UnityEngine.UIElements.UIEventRegistration:ProcessEvent <0x00233>
	  at <>c:<.cctor>b__1_2 <0x0009a>
	  at UnityEngine.GUIUtility:ProcessEvent <0x00114>
	  at <Module>:runtime_invoke_void_int_intptr_intptr& <0x001b5>
=================================================================

Last update (probably):
I tried running it on a PC (I’ve been working on a laptop) and it didn’t crash, although there was some lag. So I might continue using a PC instead… It’s not really a solution but it’s the best I could come up with