Are Scriptable Objects my best option?

After doing some reading I decided to learn Scriptable Objects. I wanted to use them in my game, as they’re extremely handy with the asset creation functionality.

However, I’ve run into a bit of a dilemma. My games Ability an Item systems are both being designed around Scriptable Objects. The player can level up abilities, and also their equipment. The Scriptable Objects are used as a template, especially for my items as these are randomly generated (stats etc.) when they are dropped.

I am struggling to figure out how to Save/Load my Ability and Item data at runtime as I’m using instances of the SO templates to create them. Can anyone advise a good way to handle my data in this fashion?

I am wondering if what I am doing is good practice, or complete misuse of Scriptable Objects altogether?

ScriptableObjects are just a newer way to store data which anyone can read from – any script in any scene can have a link to it; plus Prefabs. Before, we might put a data-holding script on a gameObject (only thing in the same scene can pre-link to it. Anyone else needs 1 extra line of code), or on a “fake” prefab (which works perfectly, but might look funny).

They’re good for storing and editing, say, the non-changing stats of abilities at each level. But not which level a player has bought. Mechanically ScriptableObjects are merely prefabs which you aren’t allowed to spawn. If a prefab can’t do something, neither can a scriptable object.

If I understand it correctly, your items are based of a SO, and then have it’s values edited randomly?

Then you can simply use a standard serialization library to serialize the item and write it into your save file. Unity’s built-in JsonUtility class is a good alternative if you’re just serializing standard SOs.

You understood exactly right. Is that a good common practice, or is there a better way? For example, my template Ability might look like this:

public Weapon : ScriptableObject
{
public int currentLevel;
public float damage;
}

Now, when a weapon is looted it will use the above SO as a template. It can then be levelled up, and it’s damage will also increase. This new data is what I would like to save. I will probably be using Odin for this as my project will have nested SO’s that Unity cannot serialize properly. When I deserialize the data, how should it know which SO template to use?

If I am on the right track, I will continue as I planned. Thanks for the reply again!

You can as well place a “container” object inside your ScriptableObject. Be it struct or class, doesn’t matter. As long as you have your properties “Serializable”.

(There’s also a way to painlessly serialize vectors / quaternions as well. Google the Surrogates, there’s an example on Unity Answers specifically for that)

Simply wrapping properties into it, and then marking it as System.Serializable will make it a breeze to serialize / deserialize.

“Current” level, or anything “current” not supposed to be in SO by design. You should store anything “current” somewhere else. On the entity you’re operating on, for example. By doing so you’ll avoid data corrupion in editor, and build as well.

Otherwise you’ll have your data stored permanently in editor and until new session starts in build. Don’t forget about that.

1 Like

Yeah, I think that’s fine.

You could consider not making it an SO, but rather making the settings for how the weapon rolls work an SO. So something like:

public class Weapon 
{
    public int currentLevel;
    public float damage;
    public Sprite icon;
    //etc
}

public class WeaponDrop : ScriptableObject 
{
    public int startLevel;
    public float minDamage;
    public float maxDamage;
    public Sprite Icon;
    //etc.

    public Weapon GenerateDrop()
    {
       return new Weapon {
            currentLevel = startLevel;
            damage = Random.Range(minDamage, maxDamage;
            icon = icon;
            //etc.
        };
    }

Non-SO objects are a bit easier to handle than SO’s, so this will nicely seperate the thing you care about at runtime (an actual weapon) and things you care about when designing (stat ranges for possible drops)

I would also recommend using JsonUtility class, as in future you can easily utilize even with other programs. Since Json is standarised format, across many programming languages. For example easy import objects to java script and do whatever.
Is dead easy to use with classes. Only downside is with dictionaries. Quaternion would be better to store as angles, for float issue resolution, and for readability.

Thanks for the help everyone. I’m going to play around a bit, using what you have all suggested, and figure out what fits best.