Arrays not serializing
Hey there,
So Ive been fighting with this kind of problem for a while now. It seems to come and disappear with no clear reason.
The arrays in my game (which I edit in the editor) sometimes serialize and sometimes not. They are always public, sometimes unity or c# native types and sometimes custom types by me.
Here is a little example:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Mapbuilder : BaseClass
{
public int[] stateProbs;
}
I edit this script here:
using UnityEngine;
using UnityEditor;
using System.Collections;
public class Window_MapBuilder : EditorWindow
{
private int width{ get { return Screen.width; } }
private int height{ get { return Screen.height - 22; } }
private Mapbuilder builder;
[MenuItem ("Custom/MapBuilder")]
private static void Init ()
{
EditorWindow.GetWindow<Window_MapBuilder> ().Show ();
}
void Update ()
{
Repaint ();
}
void OnGUI ()
{
Undo.RecordObject ((Object)this, "Edit Builder Window");
if (builder == null) {
builder = FindObjectOfType<Mapbuilder> ();
}
minSize = new Vector2 (500, 400);
if (builder.stateProbs == null || builder.stateProbs.Length != 5)
builder.stateProbs = new int[5];
for (int i = 0; i < 5; i++) {
builder.stateProbs [i] = EditorGUI.IntSlider (new Rect (10, sy, w - 40, 20), MapObjects.Tree.TreeObject.growStates [i] + ":", builder.stateProbs [i], 0, 100);
sy += 30;
}
EditorUtility.SetDirty (builder);
}
I have cut down the scripts to only the parts that seem important. If you want full ones just tell me.
Now: I can edit the array in my window and it also saves for when I hit play. It does however reset when I close Unity. A similar thing happens with an array of a custom class I made. Only that this one does not get reset completely but rather reverted to a state it had two days ago.
As you can see I already tried things like SetDirty e.g.
Now Im fresh out of ideas. You got any? :D
Help would be appreciated :D
EDIT: I should mention that Baseclass, which Mapbuilder inherits from, inherits from Monobehaviour, so Mapbuilder is basecally a Monobehaviour.
Answer by Adam-Mechtley · Mar 19, 2017 at 09:14 AM
I'm not sure why you call Undo.RecordObject()
passing the EditorWindow itself, but you should call it passing in the builder
right before you modify the properties on it. For example:
if (builder.stateProbs == null || builder.stateProbs.Length != 5) {
Undo.RecordObject(builder, "Set State Probs");
builder.stateProbs = new int[5];
}
for (int i = 0; i < 5; i++) {
EditorGUI.BeginChangeCheck();
int stateProb = EditorGUI.IntSlider (new Rect (10, sy, w - 40, 20), MapObjects.Tree.TreeObject.growStates [i] + ":", builder.stateProbs [i], 0, 100);
sy += 30;
if (EditorGUI.EndChangeCheck()) {
Undo.RecordObject(builder, "Set State Probs");
builder.stateProbs [i] = stateProb;
}
}
EditorUtility.SetDirty (builder);
That said, I generally advise people to use SerializedObject/SerializedProperty for editing a serialized field on something, as it automatically handles Undo/Redo/Dirtying/etc. It would look something like this in your case:
// ideally cache this and store in a field on the EditorWindow when builder is first found
var serializedBuilder = new SerializedObject(builder);
serializedBuilder.Update();
var stateProbs = serializedBuilder.FindProperty("stateProbs");
stateProbs.arraySize = 5;
serializedBuilder.ApplyModifiedProperties();
for (int i = 0; i < 5; i++) {
var element = stateProbs.GetArrayElementAtIndex(i);
EditorGUI.IntSlider (new Rect (10, sy, w - 40, 20), element, 0, 100, MapObjects.Tree.TreeObject.growStates [i] + ":", element.intValue);
sy += 30;
}
serializedBuilder.ApplyModifiedProperties();
Oh my god, I cannot believe it was that simple. Thanks a bunch my friend.
I now know why it did serialize in older versions of the game. At that time I had a custom inspector for my $$anonymous$$apbuilder and thus passed IT into the Undo.Record ins$$anonymous$$d of the window. Im so stupid XD
Again, thanks alot :D