How to serialize a scriptable object?

Hello, I’m trying to make a save system in my deck building game, and I’m having trouble saving the player’s deck because it is a list of “Cards” which are scriptable objects. Here’s the save script:

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

public static class SaveSystem 
{

    public static void SaveDeck(Deck deck) 
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        string path = Application.persistentDataPath + "/deck.data";
        FileStream stream = new FileStream(path, FileMode.Create);

        PlayerData data = new PlayerData(deck);

        binaryFormatter.Serialize(stream, data);
        stream.Close();
    }
}

I receive the error SerializationException: Type ‘UnityEngine.ScriptableObject’ in Assembly ‘UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null’ is not marked as serializable. on the binaryFormatter.Serialize(stream, data); line. After some research, I tried making a separate SaveDeck class in order to try to implement a copy constructor, but I don’t understand copy constructors very well, so I couldn’t get it to work. Does anyone have a suggestion for how to fix the error, or can someone give details on how to implement a copy constructor? In case it’s helpful, here’s the PlayerData that this script is pulling from:

[System.Serializable]
public class PlayerData
{
    public Card[] playerDeck; //the Card is the scriptable object, here I made it an array because a list was giving problems
    
    public int deckIndex;

    public PlayerData (Deck deck)
    {
        playerDeck = new Card[deck.GetDeckCards().Count];

        for (int i = 0; i < deck.GetDeckCards().Count; i++)
        {
            playerDeck _= deck.GetDeckCards()*;*_

}

deckIndex = deck.GetCurrentDeckIndex();
}
}
Thank you for taking a look.

Hey there,

i suggest you check out this thread on stackoverflow. Apparently Unitys internal JSON-Utility is able to parse Scriptable objects into jsonstrings which in return can be fed to a binary formatter.


Other (not so nice solutions) that you could try if number one above fails:

Regarding the copy constructor this is just a fancy name for: “Your class “X” has a seperate constructor which does not take a set of some values but instead an object of type “X” and uses that objects values to initialize the new object” → hence it copys the given object. But since the type of the class is the same this concept will not really help you here.

What instead could be done here (but is not really recommendable as this overcomplicates things) is that you create a second class “Serializable_Card” which is basically identical regarding the member variables of “Card”. Only difference: “Serializable_Card” would not inherit from ScriptableObject but would just be marked as “Serializable”. At this point you could then create a Constructor for “Serializable_Card” which takes a “Card” and then copys all values.

Also thinkable (but not really nice, please try the JSON solution) would be something like this:

public class Card : ScriptableObject
{
       public SerializableCard values;
}

[System.Serializable]
public class SerializableCard {
      int id;
      string name;
      //yaddayadda more values go here
}

Not really sure if this structure would work but in the end you could then make your Scriptable Object contain a SerializableStructure of the actual values which make up a card. (Not tested but should work)


Hope this helps, let me know if something is unclear or if you need more help.