- Home /
ScriptableObject List variable doesn't save if created through script, works fine if created through Inspector
If have an Event class that is a scriptable object which is saved in the Assets folder. The Event has a list of a different, serializable class, EventProperty as a variable. Now there are two ways to create an Event: Using Right-click -> Create or through a script. Using right click works fine and it saves the EventProperties correctly. However, if I use the script, it seems to work fine at first, but once I restart Unity the Evenproperties List is empty. Other Variables, like the Event name are saved fine however. I've seen some similar questions but none of the suggested solutions worked. Here are the relevant bits of my code, maybe I'm missing something.
First, the Event class:
[CreateAssetMenu(menuName = "VR Scientific Toolkit/STKEvent")]
public class STKEvent : ScriptableObject
{
[SerializeField]
public List<EventParameter> parameters = new List<EventParameter>();
public string eventName;
public Hashtable objects = new Hashtable();
public int uniqueID; //TODO
public float time;
public void AddParameter(string name, int typeIndex)
{
AssetDatabase.Refresh();
Undo.RecordObject(this, "Add Parameter");
EventParameter newParameter = new EventParameter();
newParameter.name = name;
newParameter.hideFromInspector = true;
newParameter.typeIndex = typeIndex;
parameters.Add(newParameter);
AssetDatabase.SaveAssets();
}
}
A part of the Editorscript where the Event is created:
private void CreateEvent()
{
//Create Event itself
STKEvent newEvent = (STKEvent)ScriptableObject.CreateInstance("STKEvent");
newEvent.eventName = "SampleName";
// [...]
AssetDatabase.CreateAsset(newEvent, "Assets/VRScientificToolkit/Events/Track"+"sample.asset");
Undo.RecordObject(newEvent, "Created Event");
AssetDatabase.Refresh();
//Create Eventsender
STKEventSender s = trackedObject.AddComponent<STKEventSender>();
s.eventBase = (STKEvent)AssetDatabase.LoadAssetAtPath("sample.asset",typeof(STKEvent));
s.SetTrackedVar(trackedComponents,trackedVariables,savedNames);
AssetDatabase.SaveAssets();
}
And lastly the Eventsender function where the Parameters are set:
public void SetTrackedVar(bool[] comps, bool[][] vars, List<string> eventVarNames)
{
//[...]
for (int i = 0; i<comps.Length; i++)
{
if (comps[i])
{
AssetDatabase.Refresh();
Undo.RecordObject(eventBase, "Created Event");
for (int j = 0; j<vars[i].Length; j++)
{
if (vars[i][j])
{
if (j >= trackedComponents[trackedCompsIndex].GetType().GetProperties().Length)
{
eventBase.AddParameter("SampleName",1);
} else
{
eventBase.AddParameter("SampleName",1);
}
varNameIndex++;
eventVariableIndex++;
}
}
AssetDatabase.SaveAssets();
trackedCompsIndex++;
}
}
}
As you can see, what I basically tried so far is putting Undo.RecordObject() and AssetDatabase.SaveAssets() everywhere something is changed about the object, but no luck. I really don't know what to do anymore, it's just weird considering the other variables are saved just fine.
Answer by felix330 · Nov 05, 2018 at 01:13 PM
I figured it out! I had to set all the variables before creating the asset. Only had to adjust the order of commands in the CreateEvent() Function a bit, so now it looks like this:
STKEventSender s = trackedObject.AddComponent<STKEventSender>();
s.eventBase = newEvent;
s.SetTrackedVar(trackedComponents, trackedVariables, savedNames);
AssetDatabase.CreateAsset(newEvent, "Assets/VRScientificToolkit/Events/Track"+trackedObject.gameObject.name+trackedObject.gameObject.GetInstanceID().ToString()+".asset");
Undo.RecordObject(newEvent, "Created Event");
AssetDatabase.Refresh();
s.eventBase = (STKEvent)AssetDatabase.LoadAssetAtPath("Assets/VRScientificToolkit/Events/Track" + trackedObject.gameObject.name + trackedObject.gameObject.GetInstanceID().ToString() + ".asset", typeof(STKEvent));
AssetDatabase.SaveAssets();
I think you can, also, check if something is null when storing it, and if it is null then initializing it
Answer by hectorux · Nov 04, 2018 at 03:29 PM
[SerializeField] makes serializable just the below property, if you want it to more variables, then you have to put one over every one
Thanks for the answer, the variable right below the [SerializeField] is the one that doesn't save though, so that can't be the problem.
Do you know if event parameter is serializable?
Yes, this is the entire EvenParameter class:
[System.Serializable]
public class EventParameter
{
public string name;
public System.Type systemType;
public int typeIndex;
public bool hideFromInspector;
public void SetTypeFromIndex()
{
systemType = ST$$anonymous$$EventTypeChecker.allowedTypes[typeIndex];
}
}
The weird thing is, it seems to serialize just fine, but only when it's created through the Unity inspector and not through my script.
Your answer
Follow this Question
Related Questions
Serialization issue with ScriptableObject 0 Answers
How to create custom asset icons for ScriptableObject instances 2 Answers
Converting XML-files into assets 1 Answer
ObjectField Get object type(Asset, Scene Object) 2 Answers
How to control class variables from an Editor Tool or external file? 2 Answers