Its my understanding that that all scripts are supposed to get serialized and rebuilt upon entering and exiting play mode, and that only public fields and [Serializable] fields are included in the serialization. However, this doesn’t seem to be the case for editor scripts…
Private and unspecified (protected?) bool appear to be getting serialized since their values don’t get reset whereas the [System.NonSerialized] value does…
I always thought [System.Serializable] just flagged the class as something that can be considered for serialization, not something where every field should be serialized, and experience with working with Unity serialization in MonoBehaviour supports this (I’ve also included a script that shows it)…
Is my understanding of what [System.Serializable] does flawed? Or is this just a bug?
Googling didn’t come up with anything particularly concrete, only that “if you want it serialized, use System.Serializable”.
I also noticed that the OnDisable/OnEnable rotation only happens when entering play mode and recompiling, and not when exiting…
Anyway- The code:
using UnityEngine;
using UnityEditor;
public class EditorSerializationTest : EditorWindow {
[MenuItem("Tarlius/Open Serialization Window Test")]
static void EditorSerializationWindowTest() {
EditorWindow.GetWindow<EditorSerializationTest>();
}
[SerializeField] DataHolder dataHolder = null;
void OnEnable() {
if(dataHolder == null) dataHolder = new DataHolder();
dataHolder.OnEnable();
}
void OnDisable() { dataHolder.OnDisable(); }
void OnGUI() { dataHolder.OnGUI(); }
}
[System.Serializable]
public class DataHolder {
bool defaultBool = false;
public bool publicBool = false;
[System.NonSerialized] bool nonSerializedBool = false;
[SerializeField] bool serializedBool = false;
public void OnGUI() {
if(GUILayout.Button("Set True" )) Set(true );
if(GUILayout.Button("Set False")) Set(false);
if(GUILayout.Button("Status")) LogButton();
}
public void OnEnable() { Log("Enable:"); }
public void OnDisable() { Log("Disable:"); }
public void LogButton() { Log("Button:"); }
public void Set(bool value) {
defaultBool = value;
publicBool = value;
nonSerializedBool = value;
serializedBool = value;
}
void Log(string context) {
Debug.Log(context);
Debug.Log("default" + defaultBool.ToString());
Debug.Log("public" + publicBool.ToString());
Debug.Log("nonSerialize" + nonSerializedBool.ToString());
Debug.Log("serialized" + serializedBool.ToString());
}
}
Use the menu item to open the window, press the button to set all the fields to true, then enter play mode. Trues go in, all but the NonSerialize gets trues back. And for those interested, here is a MonoBehaviour that shows the inconsistency. Make a gameObject in edit-mode, use the menu to set all to true, and then enter play mode. In OnEnable only the public and SerializeField come back true (which is what I expect).
using UnityEditor;
using UnityEngine;
public class SceneSerializationTest : MonoBehaviour {
[MenuItem("Tarlius/Set SceneTest True")]
static void SetupSceneTest() {
SceneSerializationTest sf = GameObject.FindObjectOfType(typeof(SceneSerializationTest)) as SceneSerializationTest;
sf.dataHolder.Set(true);
}
[SerializeField] DataHolder dataHolder = null;
void OnEnable() {
if(dataHolder == null) dataHolder = new DataHolder();
dataHolder.OnEnable();
}
void OnDisable() { dataHolder.OnDisable(); }
void OnGUI() { dataHolder.OnGUI(); }
}