1
votes

I'm using a custom Editor Script to display and adjust parameters of elements in a Reorderable List. But whenever I restart Unity and click the GameObject holding the script, these parameters are reseted (like shown in the picture at the end of the post). When I deactivate the Custom Editor Script, everything works as it should, so the problem might be in this script.

This is the Story class using the custom Editor script:

[System.Serializable]
public class Story : MonoBehaviour
{
public List<Chapter> ChapterList;
}

and the Editor Script, using a Reorderable List:

[CustomEditor(typeof(Story))]
public class StoryEditor : Editor 
{
private Story story;
private ReorderableList reorderableList;

void OnEnable()
{
    story = (Story) target;
    if (story.ChapterList == null)
        story.ChapterList = new System.Collections.Generic.List<Chapter>();
    if (reorderableList == null)
        reorderableList = 
            new ReorderableList(
                story.ChapterList,
                typeof(Chapter), 
                true, true, true, true);

    reorderableList.drawElementCallback += DrawElement;
}

private void DrawElement(Rect rect, int index, bool active, bool focused)
{
    Chapter c = story.ChapterList[index];
    EditorGUI.BeginChangeCheck();
    c.ID = index+1;
    EditorGUI.IntField(new Rect(rect.x, rect.y, 20, rect.height-1), c.ID);
    c.Title = EditorGUI.TextField(new Rect(rect.x + 21, rect.y, rect.width - 79, rect.height-1), c.Title);
    c.Hide  = EditorGUI.Toggle(new Rect(rect.x + rect.width - 56, rect.y, 17, rect.height-1), c.Hide);

    if (GUI.Button(
        new Rect(
            rect.x + rect.width - 40, rect.y, 40, rect.height-1), "Edit"))
                Select(index);

    if (EditorGUI.EndChangeCheck())
    {
        EditorUtility.SetDirty(target);
    }
}

I googled the problem, but the solutions I found mentioned to use [System.Serializable] and EditorUtility.SetDirty(target);, which I'm using both. I assume I'm missusing something in the "DrawElement" method, but I can't figure out what it is.

Image displaying the changes pre and post restarting Unity

Upper part: Before Restarting, Lower Part: After Restarting Unity.

1
Maybe you could compare your code to this answer on Unity answers. I haven't used any of this myself though.31eee384
Thanks! But this was the guide I was following, causing this problem.Jonas Zimmer
Well, it does look significantly different from that, specifically that Story has [Serializable] rather than Chapter (which I don't know if it also has [Serializable] because I don't have its code). You also don't appear to call SetDirty when items are added/removed, although maybe you've determined that's not necessary in your case. I guess what I'm suggesting is that you use this debug approach: use code identical to something that works for people and change it to what you think you need one step at a time to isolate what small change causes problems.31eee384
Thanks! I will rego through the code adding parts from the working solution. I've shortened the code example above drastically, Add/Remove also call SetDirty and Chapter is [Serializable] too.Jonas Zimmer

1 Answers

1
votes

There were several problems I've encountered while working on this issue. First: The if statement in the Editors OnEnable() method is true everytime you reselect the object holding the Story script. This seems to be because of the way Editor Scripts are working. I think they're reinstantiated whenever the user reselects the object. Therefore I moved the new List<Chapter>(); part to the Story class and implemented a Getter functionality.

private List<Chapter> chapterList;
public  List<Chapter> ChapterList
{
    get 
    { 
        if (chapterList == null)
            chapterList = new List<Chapter>();
        return chapterList;
    }
}

The next issue were the private variables. While public variables are always serializable, private values will not be serialized (allthough the class is marked as [System.Serializable], which I thought would solve this problem). To make private variables Serializeable, they have to be marked as a [SerializeField].

[SerializeField]
private List<Chapter> chapterList;
public  List<Chapter> ChapterList
{
    get 
    { 
        if (chapterList == null)
            chapterList = new List<Chapter>();
        return chapterList;
    }
}

After I add [SerializeField] to every private variable in my classes, the problem was gone.