Page 1 of 1

Scriptable Object Saver Component ?

Posted: Tue Jan 19, 2021 8:58 am
by NotVeryProfessional
I'm starting to set up the save system included in Dialogue System for my game, and things like current scene and transform positions work like a charm, very easy to use, I'm happy with that.

A lot of my game state is stored in scriptable objects, and before I puzzle out how to feed those into the save system I thought that I can't be the first one. So the question to the community - has someone written a Scriptable Object saver component already?

Re: Scriptable Object Saver Component ?

Posted: Tue Jan 19, 2021 9:12 am
by Tony Li
Hi,

Since ScriptableObjects are just regular classes with the added ability that Unity can serialize them, there isn't a one-size-fits-all solution.

Are you using ScriptableObject assets? (That is, instances of ScriptableObjects that are saved as files in your project.) Or just in-memory ScriptableObjects?

If you're using in-memory ScriptableObjects, add a script to whatever GameObject in the scene manages the ScriptableObject. Save and load it like any other object. Example ScriptableObject:

Code: Select all

public class Health : ScriptableObject
{
    public int currentHP;
}
Example script on GameObject:

Code: Select all

public class HealthManager : MonoBehaviour
{
    public Health health;
    void Awake() { health = CreateInstance<Health>(); }
}
Example saver:

Code: Select all

public class HealthSaver : Saver
{
    public override string RecordData()
    {
        return GetComponent<HealthManager>().health.hp.ToString(); // Edit: Fixed bug.
    }
    public override void ApplyData(string s)
    {
        if (string.IsNullOrEmpty(s)) return;
        GetComponent<HealthManager>().health.hp = SafeConvert.ToInt(s);
    }
}

If you're using assets, you can add a saver script to the Save System GameObject that does something similar:

Code: Select all

public class HealthAssetSaver : Saver
{
    public Health healthAsset; //<--Assign ScriptableObject asset in inspector.
    
    public override string RecordData()
    {
        return health.hp.ToString(); // Edit: Fixed bug.
    }
    public override void ApplyData(string s)
    {
        if (string.IsNullOrEmpty(s)) return;
        health.hp = SafeConvert.ToInt(s);
    }
}

Re: Scriptable Object Saver Component ?

Posted: Tue Jan 19, 2021 9:21 am
by NotVeryProfessional
I am using assets. I have generic SO classes, such as "creature" or "location" and then individual assets for each of them.

Some of those assets are static in my case (the name, graphics, hitpoints, etc. of a creature never change), while some can change during gameplay (e.g. which quests are currently available in a location).

You examples are a great starting point, thanks!

Re: Scriptable Object Saver Component ?

Posted: Tue Jan 19, 2021 10:45 am
by Tony Li
Glad to help!

Re: Scriptable Object Saver Component ?

Posted: Tue Jan 19, 2021 5:49 pm
by NotVeryProfessional
Reading a bit through the code - I'm wondering:

If my SO is serializable, can't I simply use SaveSystem.Serialize() ?

(update: made a quick test, it appears to work)

Re: Scriptable Object Saver Component ?

Posted: Tue Jan 19, 2021 6:02 pm
by Tony Li
Yes, you can certainly do that, as you wrote.

Re: Scriptable Object Saver Component ?

Posted: Wed Jan 20, 2021 1:38 am
by NotVeryProfessional
brilliant. So for anyone searching for this in the future, if your SO is serializable, a saver component is as easy as:

Code: Select all

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using PixelCrushers;

public class SomeAssetSaver : Saver {

    public SomeClass someAsset;

    public override string RecordData() {
        return SaveSystem.Serialize(someAsset);
    }

    public override void ApplyData(string s) {
        if (string.IsNullOrEmpty(s)) return;
        someAsset = SaveSystem.Deserialize<SomeClass>(s, someAsset);
    }
}

Or am I missing something here?

Re: Scriptable Object Saver Component ?

Posted: Wed Jan 20, 2021 5:54 am
by NotVeryProfessional
One more question:

In your above example, you assign variables, but don't return anything from the RecordData() method. But it requires that data is returned. I assume you left that out for brevity, or is there some magic I'm missing?

Re: Scriptable Object Saver Component ?

Posted: Wed Jan 20, 2021 8:57 am
by Tony Li
Yeesh, totally a bug. I fixed it. I was going to split it up into two lines (GetComponent on the first line, return on the second) but I got sidetracked partway through the edit and forgot to fix it. And then I copied that same bug down in the second RecordData method. :oops: