ScriptableObject Data Persitience

Looking for a way to have my data stored in a ScriptableObject asset, saved between reloads of unity.

I been able to use the ScriptableObject to save data, during runtime of the game, that is still available after i stop playing the game in the editor. But if i fully close and restart unity, the data is reverted to the last values entered via hte inspector.

The same thing happens when this is done in the final build on android, and the game is closed and launched again.

Im guess i have to serialize the data in the ScriptableObject to something that i can read and write to on the platform, but not sure how.

I am not sure it is possible to do this at runtime as I believe you would need to call setDirty on the asset via the EditorUtiliy and then save assets. However I don’t believe that EditorUtility is available in a final build.

For this scenario it may be best to create something like an XML save file that you could write to on save and then load during the next session to set the variables you have altered in the previous session.

You have a good sample of how i could just modify this existing class, to let it searlize its self than store in player prefs than

You can use playerprefs for settings.
Additionally, I have used XML serialisation to serialize data classes to files as well.
It’s fairly simple, below are methods I use to save and load an instances of a class called “CommandTree”.

The “Save” method creates an XML version of the class instance state and the static “Load” method takes the path of an XML file to load and returns an instance of “CommandTree”.

For simple classes the code below may be all you need. Then you can easily build up a save system around this. Of course there are other serialization options available if this does not suit.

    public void Save(string path)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(CommandTree));
        using(FileStream stream = new FileStream(path, FileMode.Create))
        {
            serializer.Serialize(stream, this);
        }
    }
   
    public static CommandTree Load(string path)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(CommandTree));
        using(FileStream stream = new FileStream(path, FileMode.Open))
        {
            CommandTree commandTree =
                                     serializer.Deserialize(stream) as CommandTree;
            commandTree.setParents();
            return commandTree;
        }
    }

ya i tried making this, so i could serialize and deserilzie my data, and keep it in player prefs, but it wont work when using the save method, on my object that contains the data.

using UnityEngine;
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;


public class DataStorage {
    public static BinaryFormatter bf = new BinaryFormatter();

    public static void Save(string prefKey, object serializableObject)
    {
        MemoryStream memoryStream = new MemoryStream();
        bf.Serialize(memoryStream, serializableObject);
        string tmp = System.Convert.ToBase64String(memoryStream.ToArray());
        PlayerPrefs.SetString(prefKey, tmp);
    }

    public static T Load<T>(string prefKey)
    {
        if (!PlayerPrefs.HasKey(prefKey))
            return default(T);

        string serializedData = PlayerPrefs.GetString(prefKey);
        MemoryStream dataStream = new MemoryStream(System.Convert.FromBase64String(serializedData));

        T deserializedObject = (T)bf.Deserialize(dataStream);

        return deserializedObject;
    }
}

i get this error

SerializationException: Type UnityEngine.ScriptableObject in assembly UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is not marked as serializable.

Even know the object im trying to save a ScriptableObject derived from ScriptableObject, which also contains the [Serializable] tag for good measure.

I haven’t done this myself myself, but a workaround off the top of my head would be to have your scriptable object contain a class that you save via the binary serializer (as opposed to the scriptableobject itself which the serializer doesn’t like). This class would contain state that needs saved and reloaded between play sessions. Then in the “OnEnable” method where you initialise the scriptableobject you could load in the saved state and apply it there.
This way the asset remains unchanged in the editor and you can start a new game from scratch with the default asset. It will also support multiple save files. If you modify and change the asset itself then won’t you lose its original state?

Ya thanks for the reply, that is exactly what i did, since only 6 out of 40 attributes of the object needed to be saved during the games runtime. I just made a other class that mirrors those 6 attributes, and onEnable() moved the data over.

Was one of those situations where i was learning about the scriptable objects, and that data was persisting me entering and exiting play mode. So i assumed it would survive the whole engine being restarted.

Taking a differnt approach next time, but this gets me through without changeing the rest of my codebase for now.