I’m trying to figure out how to properly set up my save game in Unity. Take this example:
Imagine a typical RPG. The player has an inventory full of items. He also has a collection of skills/spells that he’s chosen as he’s levelled up. My research into Unity best practices tells me that both the items and the skills will be set up as prefabs. The player’s runtime inventory could be set up as a List, which would contain references to instantiated GameObjects based on the prefabs.
What is the best way to save in this situation? I’ve seen some stuff that seems to suggest saving by string. That seems wasteful to me (why use a string when you can use an int?) and what I’ve read tells me that a GameObject doesn’t know its prefab name at runtime anyway.
Obviously I don’t want to just serialize the entire Item class; all of the data I need is already available. There’s simply no reason to dump all of that into a save file.
In another engine, I would probably have a list of object IDs or maybe even an index into a flat list if I was really worried about data compression (if I was sending it over the net, for instance). I just can’t find anything in Unity that seems to follow this pattern.
I’m only going to bump this once, but I’m really hoping for an answer. This seems like it must be a common problem. I would really appreciate the help.
The easiest way I have found to do this is to setup a “Serializable” version of a class you want to save.
For example, if you have a Vec3 in your Unity class, that would be converted to 3 floats or a struct containing those. This is necessary if you’re using .Net setializers, since they have no notion of what Vector3, transform, etc. are.
Now to (de)serialize that, I had a table of IDs corresponding to space ship hulls (in my last game). So the serializable class would contain ints and other .net primitives. When loading or saving, the id table would be consulted to get the actual prefab in Unity.
An object by default doesn’t know its prefab name. That doesn’t mean you can’t have a script that knows it. (Or, at least, know what name it should look for when it goes to respawn itself). Your Claymore game object has an InventoryItem script that has a string, “Claymore”; this string is serialized (along with whatever other data you need to save about the items), and when you load the game, you just spawn the item named Claymore. Only downside is, it’s a bit annoying to have to set the names of things in 2 places.
I had a ScriptableObject that had a dictionary of <int, Hull>. Hull can be replaced with whatever you need the id to correspond to.
I had a custom inspector for the SO that allowed you to drag in a prefab and then you could manually or automatically generate an id for it.
There’s no reason it has to be converted to 3 floats. Serializers can handle a Vector3 just fine for the most part. The only thing you have to be careful of is the fact that they have properties like normalized that returns another Vector3 and you can get stuck in an infinite recursion loop of serialization if the serializer isn’t made to handle it. But, whether it’s my asset (JSON .NET for Unity) or miniJSON or JsonFX or JsonObject or whatever is out there, they should be able to serialize a Vector3 just fine.
The main point of using proxies or save game classes is so you can just store off the data you want to save. My asset for instance also can’t serialize Monobehaviors so you have to use a proxy if you want to serialize the behavior itself. There are also some nice save game assets out there as well such as Easy Save 2, though I don’t have any experience with them but I’m sure someone who does can chime in.
This is incorrect if we’re talking about .Net serializers, which I was. Unless you specifically write something to handle it yourself. Which of course might have been done in the assets you reference.
Yeah, I was referring to the Binary/XML serializers that come with .Net.
By the way, this live tutorial should have exactly what you’re looking for TheChemist:
Already watched that. It’s pretty basic serialization and IO stuff. As I was saying, I don’t actually need to know how to do serialization. It’s more about figuring out how to identify a prefab in a way that can be serialized.
The solution that I’ve come up with and seems to be working so far is to generate a hash based on a string. When my game boots up, it creates some dictionaries that map the hash IDs to the classes. This gives me the mappings I need.
Not sure if this is the best way to do it with Unity, but no one has been able to offer me anything better.