- Home /
Can you use a ScriptableObject to save game state?
I have a fairly complex game which involves a lot of ScriptableObject instances at runtime. I have one ScriptableObject which manages all of these instances. I was hoping that I could somehow save the game state by just saving this managing object, using BinaryFormatter
, but I only get this error:
SerializationException: Type UnityEngine.ScriptableObject in assembly UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null is not marked as serializable.
Here's how I'm doing it:
[System.Serializable]
public class GameData : ScriptableObject {
// ... other stuff
public static void Save(GameData data) {
Debug.Log("Saving game...");
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(SavePath);
bf.Serialize(file, data);
file.Close();
}
}
What's the proper approach to saving game state?
Answer by Bunny83 · Nov 14, 2014 at 07:04 AM
No, you can't. The ScriptableObject can't be serialized with the BinaryFormatter. If you want to use the BinaryFormatter you have to use normal classes (not derived from anything (except System.object)). Normal classes can have the Serializable attribute and you can serialize them with the normal .NET serialization system. However, almost all Unity types are not supported as non of them are marked as serializable, not even the Vector3 or Color structs.
One solution is the Unity serializer originally by Mike Talbot (aka WhyDoIDoIt). He implemented a serialization system to serialize whole scenes including gameobjects, scripts, custom classes. However it doesn't seem to be continued anymore.
Since around Unity 5.3 (i think) we have the JsonUtility which can serialize almost the same things Unity can serialize at edit time. This includes most Unity valuetype types like Vector2/3/4, Quaterions, Color values, ... However it can't serialize "references" as JSON doesn't even have a concept for that. It also can't serialize UnityEngine.Object derived classes with the exception of ScriptableObjects. In addition it's possible to use "FromJsonOverwrite" to deserialize and overwrite the values of MonoBehaviour components.
Answer by WF_Bart · Feb 13, 2017 at 01:10 PM
This answer is old; you can serialize ScriptableObjects to Json with JsonUtility.ToJson, and save that to a file. Also see: https://youtu.be/6vmRwLYWNRo?t=25m45s
This should really be at the top; the original answer is no longer valid and SO's have progressed pretty far from being a "bag of bricks".
Additionally, the answer is wrong about Vector3/Color not being correctly serialized. As of Unity 2017 they are serialized appropriately.
You haven't read my answer carefully. The problem with Vector3 and Color is with the normal .NET serialization system (which includes the BinaryFormatter) since it requires all types to be marked with the Serializable attribute which Vector3 and Color are not.
Yes, since they implemented the JsonUtility class it's now possible to serialize ScriptableObjects at runtime to JSON. Though it still has several limitations. It has the same restrictions as Unity's serialization system but in addition does not support the serialization of references.
Also if you read the original question the OP wanted to use the BinaryFormatter. As i said Vector3, Quaternion and Color are not (yet?) marked as serializable and ScriptableObjects can't be serialized by any .NET serialization system as ScriptableObjects can't be created with "new".
Yes, it's an old question and at the time the question was asked there was nothing wrong with my answer. WF_Bart has has added a newer answer to mention the changes and that we can now serialize ScriptableObjects to JSON using the JsonUtility. However this question is more than 3 years old. The OP hasn't been seen here since the end of 2014 so it's unlikely he comes back to change the accepted answer because he most likely doesn't care ^^.
If i find the time i'll add some information about the new JsonUtility. However i've written over 6k answers and we have over 1.4 million posts in total here on UnityAnswer. It's impossible to keep every information up to date.
Anyway, I thought saving with JsonUtility works with ScriptableObjects in a list, but apparently they just save as instances #'s.. As much as I thought it'd work because it worked in the editor, it didn't work when built on the platform (Android in my case).
ScriptableObjects are first class serialized objects. So you have to actually serialize the instance itself. The JsonUtility is quite limited. In the usual serialization system references to ScriptableObjects are serialized as actual references unlike other classes. However JSON doesn't have a concept for references at all.
Answer by OndrejPaska · Sep 19, 2018 at 12:19 PM
You can create and inner serilializable class to hold you data:
public abstract class Variable<T> : BaseVariable {
[Serializable]
private class VariableData<TV> : VariableData
{
public TV Value;
}
public T DefaultValue;
public T RuntimeValue { get; set; }
protected void OnEnable()
{
RuntimeValue = DefaultValue;
}
public override VariableData GetData()
{
return new VariableData<T>
{
Value = RuntimeValue
};
}
public override void LoadFromData(VariableData data)
{
RuntimeValue = ((VariableData<T>) data).Value;
}
}
Read more at https://fishtrone.wordpress.com/2018/09/16/saving-scriptable-object-variables/
Answer by Wrymnn · Dec 11, 2015 at 08:02 AM
For anyone else searching for this, here you go:
public static T LoadScriptableObject<T>() where T : ScriptableObject
{
System.Type type = typeof(T);
return Resources.Load<T>(type.ToString());
}
Just put your created .asset scriptable object into Assets/Resources folder and load it via this function.
And yes, it is as simple as that :D
I think question was asked in a way that it is required to create and save this data during runtime of built game not just in editor cause that is trivial. I'm interested in this as well.
Answer by superfryme · Dec 10, 2018 at 05:03 AM
I use serialize objects for saving data I'm going to use in my game. one holds a list of all weapons with their associated game object, mesh, material and am icon I'm going to implement into gui. theoretically you can make your levels out of scripts le objects. anything that you want. it can be altered during runtime and saved to JSON and or binary like any other script that is serialized. it's great for things you want to be the same everytime you load your game...
perhaps you generate data everytime you hit play. you could do that into a scriptable object with an editor script ins$$anonymous$$d and never generate it again