Best way to know type of serialized class, before deserializing

I have an entity parent class

public class EntityClass : MonoBehaviour{
public int entID;
//some vars and methods

}

then I have some classes that inherit from it:

public class CharClass : EntityClass{

public CharStats stats;

//some other char specific vars and methods

}
public class CropClass : EntityClass{

public CropStats stats;

//some other crop specific vars and methods

}

they each take a different class for stats, which are serializable:

[Serializable]
public class CharStats{

public float WalkSpeed;

//etc more char vars

}
[Serializable]
public class CropStats{

public byte croptype;

//etc more crop vars

}

Now I want to serialize these 2 classes, cropstats and charstats, and I want to serialize them as the same filetype (.stat). I serialize them like this:

BinaryFormatter bf = new BinaryFormatter();
Filestream fs = File.Create(filepathetc + "entID.stat")

bf.Serialize(fs, new CharStats() );
//or
bf.Serialize(fs, new CropStats() );

so 1.stat could either be a file that contains either a crop or a char, so that when I initialize an char or crop entity I can do

BinaryFormatter bf = new BinaryFormatter();
Filestream fs = File.Open(filepathetc + "entID.stat", FileMode.Open)


//?.stats = ( ??? ) bf.Deserialize(fs);
//? = CharClass or CropClass
//??? = CharStats or CropStats

Since .stat files can be either from chars or crops, is there a way before I deserialize the file to know if I should be creating a CharClass and deserializing the .stat as (CharStats) in this setup?

I can solve this by creating an extra file that has info if entID=1 is either a crop or a char, but I was just wondering if there was a way to know the type of class a file was serialized as before deserializing it, sorry if it is obviously not possible since to know what is inside a file it it has to be opened first.

Thanks!

I don’t know if there’s a way to do this cleanly with BinaryFormatter. If nothing else, you can use try … catch - try to deserialize as CharStats, if you catch an exception of a particular kind, then try to deserialize as CropStats.

It’s not binary formatting, but Json.NET supports doing this if you create a JsonSettings with TypeNameHandling set - you can save the type name into the file and that’s the type of object it’ll create when it deserializes it. (maybe there’s something equivalent in BinaryFormatter but I’m not aware of anything)

1 Like

thanks I will look into it

ScriptableObjects (Manual) are Unity’s in-built solution to solve your problem. They allow you to create data instances of a definition and reference them in your scripts, allowing you to load and unload them as you need to, without the need of handling serialization and deserialization yourself. Addressables (Manual) go even further.

ScriptableObjects and Addressables are for an entirely different use case. This is about the saving persistent data at runtime, not creating data in the editor.

Where does OP say this? They merely talk about serialization and deserialization of data objects from files, which is exactly what SOs solve. I don’t see any sentence about saving persistent data at runtime.

If you absolutely need to know the type before deserializing from binary format, you can review this post to learn how to interpret the binary header info: c# - How to analyse contents of binary serialization stream? - Stack Overflow

However, keep in mind that BinaryFormat.Deserialize returns an object. You don’t typically need to know ahead of time what kind of object will be returned because you can call .GetType() on the object once you have it in hand.

Also keep in mind that binary serialization is a highly specialized kind of serialization with a specific use case. A textual based serialization, such as JSON, is much easier to work with and is more commonly used.

1 Like

To clarify, my goal is indeed for the purposes of saving and loading data at runtime and keeping it between sessions. As a side question could you point me to the benefits of JSON over binary? It makes a human readable file and is easier to access without deserializing?

Does JSON have wide compatibility with multiple platforms? ( does it work with android and IOS more precisely?)

Thanks everyone for the help!

The primary benefits of a serialization protocol like JSON is human readability. It makes it easier for you and potential future devs or mods to work with.

In terms of compatibility, because these are protocols built on top of cross-platform software, there shouldn’t be a difference between Android, IOS or Windows. However, because JSON is more commonly used, I think you will find much better support for it over binary serialization.

A more tangible problem you will encounter is version compatibility. If you continue development, it’s likely you will need to change the fields on your classes. Troubleshooting problems caused by adding, removing, or renaming fields is a quagmire already without adding an unreadable serialization format into the mix.

1 Like