x


OnInspectorGUI changes reset when played in editor or building

I've created a custom inspector for a tile-based system I'm working on. The target's layout (the number and orientation of the tiles it takes up) is represented as a 2D list of boolean values (eg List<List<bool>>). The new inspector appears to work fine, adding and removing columns and rows as expected. If I go between an prefab with a MyClass MonoBehaviour and some other object, the layout values remain as expected. Pressing play or initiating a build, however, causes the values to get reset to the default. Am I wrong in believing that EditorUtility.SetDirty (target) should cause these values to be set in the target MonoBehaviour. Why does playing the scene cause the values to be reset?

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

[CustomEditor (typeof(MyClass))]
public class FurnitureEditor : Editor
{

    public override void OnInspectorGUI ()
    {
        MyClass tile = target as MyClass;
        DrawDefaultInspector ();
        EditorGUILayout.Separator ();
        GUILayout.Label ("Layout");
        EditorGUILayout.BeginHorizontal ();
        if (GUILayout.Button ("Add Row"))
        {
            tile.layout.Add (new List<bool> ());
            for (int i = 0; i < tile.layout[0].Count; i++)
            {
                tile.layout[tile.layout.Count - 1].Add (false);
            }
        }
        if (GUILayout.Button ("Add Column"))
        {
            foreach (List<bool> boolList in tile.layout)
            {
                boolList.Add (false);
            }
        }
        EditorGUILayout.EndHorizontal ();
        EditorGUILayout.BeginHorizontal ();
        if (tile.layout.Count == 1)
        {
            GUI.enabled = false;
        }
        if (GUILayout.Button ("Remove Row"))
        {
            tile.layout.Remove (tile.layout[tile.layout.Count - 1]);
        }
        GUI.enabled = true;
        if (tile.layout[0].Count == 1)
        {
            GUI.enabled = false;
        }
        if (GUILayout.Button ("Remove Column"))
        {
            foreach (List<bool> boolList in tile.layout) {
                boolList.Remove (boolList[boolList.Count - 1]);
            }
        }
        GUI.enabled = true;
        EditorGUILayout.EndHorizontal ();
        for (int row = 0; row < tile.layout.Count; row++)
        {
            EditorGUILayout.BeginHorizontal ();
            for (int col = 0; col < tile.layout[row].Count; col++)
            {
                if (row == 0 && col == 0)
                {
                    //Must always take up at least one square.
                    tile.layout[row][col] = EditorGUILayout.Toggle (true);
                }
                else
                {
                    tile.layout[row][col] = EditorGUILayout.Toggle (tile.layout[row][col]);
                }
            }
            EditorGUILayout.EndHorizontal ();
        }
        if (GUI.changed)
        {
            EditorUtility.SetDirty (target);
        }
    }
}
more ▼

asked Jun 16 '10 at 07:06 PM

burnumd gravatar image

burnumd
3.3k 22 34 71

As it seems no one has an answer, I've filed a bug on this issue. If there turns out to be a workaround or it's confirmed to work in a future version of Unity, I'll update with an answer.

Jun 28 '10 at 09:07 PM burnumd
(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

I think EditorUtility.SetDirty(target) only sets changes of attributes that are being serialized.

A possible answer to this is that you have to set the [SerializeFiled] tag in each field of the class (Myclass in this case) you want to serialize in the inspector.

In this case I suppose it would be

[SerializeField]
private List<List<bool>> layout = new List<List<bool>>(); 

If you are using DrawDefautlInspector() and don't want the private item to show, you can add HideInInspector to hide it.

[SerializeField, HideInInspector]
private List<List<bool>> layout;

Putting it this way make Unity understand that this attribute must be serialized, and not shown in the inspector (altough that double list is not standard for unity, so probably it wont be shown either).

Another possible problem is that you may be making some "reintialization" of the code somewhere in your MyClass script, try to check that out (Maybe in Start() or Awake()).

A third possible solution is to enable the tag [ExecuteInEditMode()] in Myclass, to guarantee that the first true intialization takes place in the editor, and not when you play the game.

[ExecuteInEditMode()]
public class MyClass : MonoBehaviour
{
    ...
}

I hope this will help you. Italo F. Capasso B. AKA "Edwood Grant"

EDIT

Upong checking it further, it seems that List<List<bool>> cannot be serialized. So you must create another type of structure. For example a serialized class that contains a serialized list. (Usgin either public varsiables, or setting [SerializeField] on private variables.

[System.Serializable]
public class Row
{
    public List<Bool> value = new List<Value>();
}

public class MyClass : MonoBehaviour
{
    public List<Row> columns = new List<Row>();
}

This should definetly work, and it wil even be shown in the default inspector with DrawDefautlInspector()

Italo F. Capasso B. AKA "Edwood Grant"

more ▼

answered Jul 28 '10 at 11:03 PM

edwood_grant gravatar image

edwood_grant
188 2 3 12

Thanks for your suggestions. SerializeField and ExecuteInEditMode didn't seem to work, sadly. I don't think it's a problem in Start/Awake, because the reset happens even to prefabs in the project pane as soon as I hit play (even if it's an empty scene).

Jul 29 '10 at 01:56 PM burnumd

Well I've been cheking by myself, and it looks like List<List> cannot be serialized, you will have to use another kind of construct to make that work... I managed to do it by creating a serializable class that contains bool list, and then create another list in MyClass that contains the list of that class

Jul 29 '10 at 06:28 PM edwood_grant

Huh. That's an onerous way of having to go about it, but thanks! If you'd care to type that up in an answer, I'd like to mark it as answered appropriately.

Aug 02 '10 at 01:52 PM burnumd

I was having a similar issue. SetDirty worked for me. Thanks edwood.

Nov 21 '12 at 09:51 PM Lukas_GMC
(comments are locked)
10|3000 characters needed characters left

I'll bite :), List> cannot be serialized.

I'd need to check, but I think we fixed this for Unity3.

more ▼

answered Sep 11 '10 at 08:51 PM

Lucas Meijer 1 gravatar image

Lucas Meijer 1 ♦♦
7.9k 19 43 85

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x1663
x463
x347
x56

asked: Jun 16 '10 at 07:06 PM

Seen: 3336 times

Last Updated: Nov 21 '12 at 09:51 PM