Scriptable Object Saver Component ?

Announcements, support questions, and discussion for the Dialogue System.
Post Reply
NotVeryProfessional
Posts: 150
Joined: Mon Nov 23, 2020 6:35 am

Scriptable Object Saver Component ?

Post 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?
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Scriptable Object Saver Component ?

Post 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);
    }
}
NotVeryProfessional
Posts: 150
Joined: Mon Nov 23, 2020 6:35 am

Re: Scriptable Object Saver Component ?

Post 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!
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Scriptable Object Saver Component ?

Post by Tony Li »

Glad to help!
NotVeryProfessional
Posts: 150
Joined: Mon Nov 23, 2020 6:35 am

Re: Scriptable Object Saver Component ?

Post 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)
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Scriptable Object Saver Component ?

Post by Tony Li »

Yes, you can certainly do that, as you wrote.
NotVeryProfessional
Posts: 150
Joined: Mon Nov 23, 2020 6:35 am

Re: Scriptable Object Saver Component ?

Post 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?
NotVeryProfessional
Posts: 150
Joined: Mon Nov 23, 2020 6:35 am

Re: Scriptable Object Saver Component ?

Post 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?
User avatar
Tony Li
Posts: 22049
Joined: Thu Jul 18, 2013 1:27 pm

Re: Scriptable Object Saver Component ?

Post 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:
Post Reply