Saving scriptable objects

I have created a bunch of scriptableobject assets which I am using to track equipment for a game. I have a list of these assets stored in a script which I am trying to serialize using binary formaters. However when I try to do so I get the below error. So it looks like that I could create a non scriptable object class and move all the data over before I serialize. But if I do then I lose the ability to create the assets in the editor. I am just looking for some guidance on what the best way to continue would be.

Error (when calling the saveGame() method)
SerializationException: Type UnityEngine.ScriptableObject in assembly UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is not marked as serializable.

using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
public class GameCore : MonoBehaviour
{
   public static GameCore baseGame;
  
   public List<GameItem> gameItemList;  // the scriptable object in question
  
   void Awake()
   {
     if( baseGame == null )
     {
       DontDestroyOnLoad( gameObject );
       baseGame = this;
     }
     else if( baseGame != this )
     {
       Destroy( gameObject );
     }
   }
   public void saveGame()
   {
     BinaryFormatter bf = new BinaryFormatter();
     FileStream file = File.Create( Application.persistentDataPath + "/inventroy.dat" );
     bf.Serialize( file, gameItemList );
     file.Close();
     Debug.Log ("List Saved");
   }
  
   public void loadGame()
   {
     if( File.Exists( Application.persistentDataPath + "/inventroy.dat" ) )
         {
       BinaryFormatter bf = new BinaryFormatter();
       FileStream file = File.Open( Application.persistentDataPath + "/inventroy.dat", FileMode.Open );
       gameItemList = (List<GameItem>)bf.Deserialize(file);
       file.Close();
       Debug.Log( "Loaded List" );
         }
   }
}

Did you mark your Gameitem class as serializable??

Yes I have marked it as serializable

using UnityEngine;
using System;
using System.Collections;

[Serializable]
public class GameItem : ScriptableObject
{
    public string itemName;
    public float itemWeight;

    public string getInfo()
    {
        return itemName + " - " + itemWeight.ToString () + " lbs";
    }
}

try making a wrapper class?

[Serializable] public class GameItemList: List<GameItem> {}

or use GitHub - jacobdufault/fullserializer: A robust JSON serialization framework that just works with support for all major Unity export platforms.

I just tried to add a wrapper but I got the same error

the wrapper class

using UnityEngine;
using System;
using System.Collections;

[Serializable]
public class GameItemWrapper
{
    public GameItem wrappedItem;
   
    public GameItemWrapper() {}
   
    public GameItemWrapper( GameItem obj ) { wrappedItem = obj; }
}

the new save method

    public void saveGame()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create( Application.persistentDataPath + "/inventroy.dat" );

        List<GameItemWrapper> wrappedList = new List<GameItemWrapper>();

        foreach( GameItem xItem in gameItemList )
        {
            wrappedList.Add( new GameItemWrapper(xItem) );
        }

        bf.Serialize( file, wrappedList );
        file.Close();

        Debug.Log ("List Saved");
    }

I’m pretty sure you can not serialize generics???

wrap the generic list that you serialize in a class

[Serializable] public class GameItemList: List<GameItem> {}

so that this line

List<GameItemWrapper> wrappedList = new List<GameItemWrapper>();

changes too

GameItemList wrappedList = new GameItemList();

I am still getting the error when I try to run the saveGame() method. The error is on the bf.Serialize( file, wrappedList ); line.

    public void saveGame()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create( Application.persistentDataPath + "/inventroy.dat" );

        GameItemList wrappedList = new GameItemList();

        foreach( GameItem xItem in gameItemList )
        {
            wrappedList.Add( xItem );
        }

        bf.Serialize( file, wrappedList );
        file.Close();

        Debug.Log ("List Saved");
    }

You’re still attempting to serialize something that can’t be. You don’t need a wrapper as that just wraps around the SO before writing to disk and it, again, cannot be written to disk. Instead, create a SaveGameItem class that is serializable. Give it a copy constructor that reads in your SO. Then do something like:

foreach( GameItem xItem in gameItemList )
{
    wrappedList.Add( new SaveGameItem(xItem) );
}

Then it should work

2 Likes

It works, thank you for taking a look at it.

Can you explain why does this work?What Mike pointed out works. But I dont understand why it works. Anyone know any documentation on this?Im very confused,I need good detailed information

At first, OP tried to serialize a list of SO which he can not do.
He just creates a new class which holds the same values of the scriptable object he wants to save.
The constructor for this class takes the SO and just copy it’s values.
He can now mark the new class he made as serializeable and save or load it as he wish.

1 Like

I honestly have no memory of writing that and just had an out of body experience. :slight_smile:

I’m glad @ShokeR0 was able to answer it so quickly! Thanks!

This is the right answer. There is so very much misinformation that is more easily found via Google. I just figured there must be a way to do this, and so I persisted in changing the search terms around until I found an answer I liked. I wish there was a way to mark this as “Googleable”.

2 Likes

I did the same thing, but I still get the error:

SerializationException: Type UnityEngine.ScriptableObject in assembly UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is not marked as serializable.

When calling save…

Make sure your SaveGameItem class doesn’t inherit from ScriptableObject or anything. It’s gotta be a simple, standalone, serializable class.

[System.Serializable]
public class SaveGameItem
{
    public string name;
    public float weight;

    public SaveGameItem(GameItem a_Item)
    {
        name = a_Item.name;
        weight = a_Item.weight;
    }
}
1 Like

Since its been necro’s, JsonUtility is a much friendlier way to serialize things. It takes advantage of Unity’s own serialization system, which means you get consistent behavior everywhere.

1 Like

If only UnityEngine.Object base class was marked serializable, things would be so much more fun with unity.

3 Likes