- Home /
How to correctly modify lists in editor? (changes to lists not changed or corrupted)
I am trying to build an editor for placing roads where the editor will record the position of each road on a mono behavior script. Then when a new road is placed, it uses that information to know what kind of road to place (straight, dead-end, T intersection, 4-way intersection, turn). It will also update the existing roads to account for the newly placed road.
The problem I am running into is unity seems to have some major hang-ups on updating lists in editor mode, and I can't seem to get around them. I boiled it down to the simplest script I could think of to have a good example. See the following:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class Debugafier : MonoBehaviour
{
public List<float> ExampleList = new List<float>();
}
#if UNITY_EDITOR
public class DebugWindow : EditorWindow
{
private static DebugWindow m_ActiveWindow = null;
[MenuItem("Tools/Debug...")]
static void Init()
{
// Get existing open window or if none, make a new one:
if (m_ActiveWindow != null)
{
m_ActiveWindow.Close();
}
m_ActiveWindow = (DebugWindow)EditorWindow.GetWindow(typeof(DebugWindow));
}
void OnGUI()
{
EditorGUILayout.BeginVertical();
if (GUILayout.Button("Add 2 remove 1"))
{
Debugafier debugafier = GameObject.Find("Debugafier").GetComponent<Debugafier>();
EditorUtility.SetDirty(debugafier);
debugafier.ExampleList.Add(debugafier.ExampleList.Count);
debugafier.ExampleList.Add(debugafier.ExampleList.Count);
debugafier.ExampleList.Remove(1);
}
if (GUILayout.Button("Remove 1"))
{
Debugafier debugafier = GameObject.Find("Debugafier").GetComponent<Debugafier>();
EditorUtility.SetDirty(debugafier);
debugafier.ExampleList.RemoveAt(1);
}
if (GUILayout.Button("Create New List 0"))
{
Debugafier debugafier = GameObject.Find("Debugafier").GetComponent<Debugafier>();
EditorUtility.SetDirty(debugafier);
debugafier.ExampleList = new List<float>();
}
if (GUILayout.Button("Create New List 10"))
{
Debugafier debugafier = GameObject.Find("Debugafier").GetComponent<Debugafier>();
EditorUtility.SetDirty(debugafier);
debugafier.ExampleList = new List<float>(10);
}
if (GUILayout.Button("Create Pre Filled List"))
{
Debugafier debugafier = GameObject.Find("Debugafier").GetComponent<Debugafier>();
EditorUtility.SetDirty(debugafier);
debugafier.ExampleList = new List<float>() {1,2,3,4,5};
}
EditorGUILayout.EndVertical();
}
}
#endif
So based on what is written there, the expected behavior is when the user opens up the Debug Window and clicks the Add 2 Remove 1 button, it adds 2 items to the list, then removes the item in slot 1, with an end result of the list growing by 1.
In reality, this works, twice, before going batshit insane. Starting with a list Click once and you get a list of {0}. Click again and you get a list of {0, 2}. So far so good. But here's where it gets strange. Click a third time and you get a list of {0,2,2,3}. It just... completely skips removing the item. And from that point continues to always go up by 2 and constantly fails to remove the item at index 1, in spite of logging no errors indicating a problem.
I even tried breaking on the problem area and I just watch it gracefully step over the RemoveAt() command without actually removing the item.
The "Remove" button seems to work fine, as do the "Create new List 0" and "Create Pre Filled List" However the "Create New List 10" command, which I would expect to populate the example list slot with a list with a size of 10, instead just creates an empty list again.
I also tried using SetDirty() below the change as well as above it and that does not appear to have any effect. Any help explaining why this is happening and more importantly how to get around it would be greatly appreciated.
instead of making an editor script you could try utilizing OnValidate() it is called whenever a value is changed and works in editor as well. Even works on scriptableObjects.
I don't think that's applicable in this situation. I have used OnValidate() before and it has proven helpful but unless I am mistaken that runs on the script when a value is changed.
The problem here is that when I change the value (the contents and length of the list) it does not update correctly. So anything OnValidate() could do would be after the change already failed.
Your answer
![](https://koobas.hobune.stream/wayback/20220613031311im_/https://answers.unity.com/themes/thub/images/avi.jpg)