How to save scriptableObject data in runtime?

Hello everyone Yes, I know that it is impossible to save Scriptableobject data, but maybe there is someone who still knows how to do it?

Let me explain the situation: I have character data recorded in SO. They have leveling variables, current weapons, and other changeable data. During the game session, I noticed that I can change the data, but when restarting Unity, some come back.

I do not know any other way to save data (if you advise me or even sort it out in detail, I will be very grateful), so I use such a “dirty” method.
Thank you for your help!

ScriptableObjects are not appropriate for runtime data saving. They are intended for authoring data.

YES they can be used. NO they cannot be freely serialized/deserialized because they derive from UnityEngine.Object

Loading saving is an EXTREMELY well-understood well-studied process. Avail yourself of all sources of data, and don’t try to reinvent something so simple and fundamentally complete. It has already been done many times with tutorials on how to do it all. Learn from others.

Load/Save steps:

https://discussions.unity.com/t/799896/4

An excellent discussion of loading/saving in Unity3D by Xarbrough:

https://discussions.unity.com/t/870022/6

Loading/Saving ScriptableObjects by a proxy identifier such as name:

https://discussions.unity.com/t/892140/8

When loading, you can never re-create a MonoBehaviour or ScriptableObject instance directly from JSON. The reason is they are hybrid C# and native engine objects, and when the JSON package calls new to make one, it cannot make the native engine portion of the object.

Instead you must first create the MonoBehaviour using AddComponent() on a GameObject instance, or use ScriptableObject.CreateInstance() to make your SO, then use the appropriate JSON “populate object” call to fill in its public fields.

If you want to use PlayerPrefs to save your game, it’s always better to use a JSON-based wrapper such as this one I forked from a fellow named Brett M Johnson on github:

https://gist.github.com/kurtdekker/7db0500da01c3eb2a7ac8040198ce7f6

Do not use the binary formatter/serializer: it is insecure, it cannot be made secure, and it makes debugging very difficult, plus it actually will NOT prevent people from modifying your save data on their computers.

https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

can I create 1 script that will “absorb” the data and save it? (inventory, resources and character data)
how do I transfer data for saving, do I make them static?

Yes

Are you unable to read what I posted above?

I fell into a bit of a stupor, trying to explain how to implement it correctly

Hi, is very easy actually.

Use AssetDatabase.CreateAsset(asset, path).
Than SaveAssets()

It’s important to use .asset on end of path!

Example that i’m using on current project:

public static void CreateAsset(BezierVariables vars, Bosses.Projectiles.Bosses boss, string name) 
{
     BezierObject newObject = ScriptableObject.CreateInstance<BezierObject>();
     newObject.curve = vars;

     string bossName = Enum.GetName(typeof(Bosses.Projectiles.Bosses), boss);
     AssetDatabase.CreateAsset(newObject, $"Assets/Resources/Projectiles/{bossName}/{name}.asset");
     AssetDatabase.SaveAssets();
}

They’re talking about runtime, ergo, in a build.

Your code isn’t suitable for a build.

Sorry to hear that. Let us know how it goes. I like this guy’s approach and I always work in micro tiny baby steps myself, making sure each part works before moving on.

Imphenzia: How Did I Learn To Make Games:

Two steps to tutorials and / or example code:

  1. do them perfectly, to the letter (zero typos, including punctuation and capitalization)
  2. stop and understand each step to understand what is going on.

If you go past anything that you don’t understand, then you’re just mimicking what you saw without actually learning, essentially wasting your own time. It’s only two steps. Don’t skip either step.

If you do fall into a stupor doing a tutorial, it’s always best to step back and return to the task afresh. You can’t really miss any parts of this. Software is 100% or nothing really.

The post is a year old but for the sake of others who may stumble upon it.

Like all UnityEngine.Objects serialization has to be handled separately.

public class PlayerData : ScriptableObject
{
    [field:SerializeField]
    public int Health {get;private set;}

    public void Save()
    {
        var data = new PlayerDataSerializable
        {
            Health = Health
        };

        string json = JsonUtility.ToJson(data, true);
        string path = Path.Combine(Application.persistentDataPath, SaveFileName);
        File.WriteAllText(path, "playerData.json");
    }

    public void Load()
    {
        string path = Path.Combine(Application.persistentDataPath, SaveFileName);

        if (File.Exists(path))
        {
            string json = File.ReadAllText(path);
            var data = JsonUtility.FromJson<PlayerDataSerializable>(json);
            Health = data.Health;
        }
        else
        {
            Debug.LogWarning("Save file not found");
        }
    }
}

[Serializable]
public class PlayerDataSerializable
{
    public int Health;
}

By no means the best way to do it. Just ‘a way’ to do it. Essentially, when it comes to runtime serialization, you gotta do it yourself.