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.
In the following code, my behaviour holds a datastructure instance and a primitive value. The primitive value (compValue) is correctly saved, but the data structure instance (data) is not. It is set back to null, and losing then its value. Note that this happens only with prefabs, not with scene objects, so I’m probably missing something related to prefab saving, but the weird thing is that compValue is correctly saved…
The behaviour:
using UnityEngine;
public class ComponentA : MonoBehaviour
{
public int compValue;
public DataStructureA data;
}
The data structure:
using UnityEngine;
using System;
[Serializable]
public class DataStructureA : ScriptableObject
{
public int value;
}
The editor:
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(ComponentA))]
public class EditorA : Editor
{
public override void OnInspectorGUI()
{
ComponentA component = target as ComponentA;
if (component.data==null)
component.data = (DataStructureA) ScriptableObject.CreateInstance(typeof(DataStructureA));
component.compValue = EditorGUILayout.IntField("compValue", component.compValue);
component.data.value = EditorGUILayout.IntField("dataValue", component.data.value);
EditorUtility.SetDirty(component);
}
}
Please, do you have any idea how to solve the problem ?
(I’m on unity 3.5.2f2)
Argh, it does not seem to be solved actually. Indeed, setting the component.data to dirty solved it, but as soon as I removed the component.compValue field, it does not work anymore. So I’m still lost…
Here is the new code that shows the problem.
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);
}
}
In the editor I tried removing EditorUtility.SetDirty(component) but it does not improve. Anyone has an idea on that ? or some pointers that could help me clarify the situation ?
By the looks of it, I’m pretty sure it’s how you’re using ScriptableObjects that’s throwing it. They’re designed to either be standalone assets in the project (alongside your meshes, scripts etc) or instantiated at runtime like prefabs, which is why they seem to be disappearing during the serialization step.
It’s likely that you’ll want to create an instance of your scriptable object class then save it as a .asset file so that the data can be serialized as is, and not under another prefab
From a design point of view though, is there a particular reason you want the data to be held in a scriptable object as opposed to having the values directly in your component?
Thanks Aniani for your answer. You are right, that’s caused by ScriptableObject, and your solution is also what I tried and it now works. For those interested, it looks something like: