- Home /
The question is answered, right answer was accepted
Serialization with custom editor, prefab not saving (again)
Hi, I noticed this question has been raised a lot of times, but I didn't see a solution that works for me, maybe I missed it.
I've got a MonoBehaviour holding some data structure and made a dedicated editor for that behaviour. Modifying the data structure through the editor on a scene object works nicely, but when creating a prefab with this behaviour attached to it, modifications of the data structure are not saved upon scene load.
Here are my scripts:
The behaviour:
using UnityEngine;
public class NewComponent : MonoBehaviour
{
public NewDataStructure data;
}
The data structure:
using UnityEngine;
using System;
[Serializable]
public class NewDataStructure : ScriptableObject
{
public int value;
}
The editor:
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(NewComponent))]
public class NewEditor : Editor
{
public override void OnInspectorGUI()
{
NewComponent component = target as NewComponent;
if (component.data==null)
component.data = (NewDataStructure) ScriptableObject.CreateInstance(typeof(NewDataStructure));
component.data.value = EditorGUILayout.IntField("dataValue", component.data.value);
EditorUtility.SetDirty(component);
EditorUtility.SetDirty(component.data);
}
}
Can you please help me with this problem ?
Answer by Bunny83 · May 23, 2012 at 01:02 PM
You should use a SerializedObject to modify values of a serialized object.
You don't even have to create one manually. Unity now creates one automatically for you: Editor.serializedObject. The SerializedObject also allows multi objects editing if you need it.
See also SerializedProperty
thanks for your answer. Could you be a bit more specific please? For instance, if I try using SerializedObject and SerializedProperty, I assume I let unity draw the inspector fields itself, but then I guess I need to create an editor class for my data structure. I tried, but it does not allow me to edit the value field directly, only if I double click on it. $$anonymous$$oreover, if I try creating a prefab, it does not save either. Here's the code I tried:
In class NewEditor: SerializedProperty property = serializedObject.FindProperty("data"); EditorGUI.PropertyField(GUILayoutUtility.GetRect(0f, 16f), property); serializedObject.Apply$$anonymous$$odifiedProperties();
In a new class DataEditor: SerializedProperty property = serializedObject.FindProperty("value"); EditorGUI.PropertyField(GUILayoutUtility.GetRect(0f, 16f), property); serializedObject.Apply$$anonymous$$odifiedProperties();
How would you do the specific example I provided ?
I just realised you used a ScriptableObject as data class. That can cause your problem. ScriptableObjects are serialized seperately. They are actually own assets. If you create a ScriptableObject it resists in the scene and get saved along with the scene. If you want to use a Scriptable object in a prefab, the ScriptableObject have to be saved to a true asset.
The easier way is to not inherit from ScriptableObject ;). Normal C# classes are serialized along with the object that holds the reference.
The advantage of ScriptableObjects are since they are true "Unity" objects, they can be referenced from multiple scripts / object instances. If you create a normal data class and reference it from two different script instances, after serialization / deserialization each script has it's own independent version of that class.
So generally if references to Unity objects get serialized, only a reference to the asset will be stored. If a reference to a normal (C#) data class get serialized, the actual content of that class is saved along with the script that contains the reference.
It sounds a bit complicated, but it's quite easy once you get it ;)
oh ok perfect. I get it. It indeed works without inheriting from ScriptableObject! Actually in my whole project I needed ScriptableObject because I require inheritance as your own answer suggested : http://answers.unity3d.com/questions/245604/does-unity-serialization-support-inheritence.html I think I'll now try to save the ScriptableObject as a true asset as you propose. Thanks a lot for your detailed answer!
Follow this Question
Related Questions
Using a custom editor script with a prefab instance causes my variables to reset on Play 3 Answers
Serializing a ScriptableObject without creating an asset for it? 2 Answers
How to save variables in editor, to use them during play mode 0 Answers
Storing and Retrieving Data from a ScriptableObject 1 Answer