Surprisingly, in my 7 years of Unity programming I have never had to save a game state beside just player score or some minor data like that. I managed to avoid large game states
But this time, I’m working on a bigger open world game where I need to save state of many items in the game world.
This is probably something that has been asked a gazillion times, but I just can’t seem to find anything useful online. Most googles will guide me to some Editor serialization thing, which I don’t need, I just need runtime game state serialization; or some very tedious technique. There is a lot of missleading and also outdated informulation, so I’m kind of lost in the noise of information, and I decided to ask the forum directly. So…
Lets say the game will have many different “items”, each item shares a world position, and each item will have it’s own specific data. For example here is two as an example:
- An Umbrella, which can be open or closed
- A Flashlight, that has a battery level and can be on or off.
So, I started building a system which separates the data from monobehaviors and the data is serialized, with a base class of ItemData, which will store the position, so, something like this:
[Serializable]
class ItemData
{
public Vector3 position;
}
[Serializable]
class Flashlight : ItemData
{
public bool isOn;
public bool batteryLevel;
}
[Serializable]
class Umbrella : ItemData
{
public bool isOpen;
}
And then I would have a Game class that stores the list of all items. Sounds logical, right?
[Serializable]
class Game
{
public List<ItemData> items;
}
But then I discovered that unity serialization, either JSON or binary, doesn’t support polymorphism. So, the serializer is not aware of the derived classes and will only save the data from the base class (the type of which the list is). So, putting both Umbrellas and Flashlights will not work, and only position will be saved. Also, when attempting to deserialize there is no way to figure out to which class to cast to (but there is no data anyway).
Since there is no polymorphism, the only way to actually save game state is to add both types into the Game class, so:
[Serializable]
class Game
{
public List<Flashlight> flashlights;
public List<Umbrella> umbrellas;
}
Now this works, but it’s very tedious and I would love to avoid needing to add every new item class to the Game class. Actually, not just here, I need to add stuff to 4 more places in the serialization and deserialization implementation. Considering I will add dozen more items, this I fear will be extremely tedious and error-prone.
I have asked a friend who is making an open world game and I was surprised that his technique is even 10x more tedious because he saves every property manually for every new class. Additionally his every serialized item has a lists of boolprops, floatprops, etc. that get serialized into a gigantic XML file (where most of those prop lists are empty). That works fine for him, but to me it sounds like something that surely must have a much better solution.
So, the main question is: Is there a way to serialize many different classes, without too much tediousness when creating a new class (something that I intended in the first example)?
Also, I guess that someone might say something like “You could do that with Reflection”, I’m not a big fan of reflection, plus I would be able to safely build to IL2CPP too. So, if it would be possible to avoid reflection that’d be great. But if there is a reflection solution that doesn’t break with IL2CPP that would be great too.
PS: Also, while googling, I found a unity roadmap entry that says “polymorphic serialization”, but if this forum post (threads/serializereference-attribute.678868/) is the thing that it is refering to, it seems like that is actually not what would be useful in my case.