Two copies of variables declarations, necessary to serialize?
Was working thru the excellent beginner tutorial "Persistence - Saving and Loading Data" by Mike Geig at https://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/persistence-data-saving-loading ...
Question: is it necessary to duplicate all the variable declarations I want to serialize?
At the top he declares:
public float health;
public float experience;
And down at the bottom he declares:
[SERIALIZABLE]
class PlayerData {
public float health;
public float experience;
}
Easy enough for two variables, but my data model is growing enormous as I develop a project, and the variables evolve under constant remodeling, and it's increasingly difficult to keep the whole set of declarations identical in two different places. Am I missing an easier way? Not doing anything fancy, just storing basic strings and ints and floats, but it's gonna be so-o-o many ... there must be a clever solution. Help please!
Answer by Alec-Slayden · May 25, 2016 at 07:08 AM
No, it is not necessary, however it is necessary to keep your saved data in a writable class; you can't serialize monobehaviours properly with the binary formatter.
If you are careful to keep it organized and encapsulated, and you remember that the individual references will change upon a save / load, then when you load (deserialize) data back into its class form you can send that to your actors and have them dip into it instead of their own fields.
However, it may become questionable practice if the majority of a scripts fields are all held in containers instead of the script itself.
Keeping scripts from getting too long, and keeping data (including save data) encapsulated to specific purposes, as well as only saving critical things and avoiding unnecessary detail, may help alleviate copypasta and bloated load methods.
Edit: Here's an example of some sci-fi game save management script that might utilize values through the class containers instead of explicit declarations:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class GameDataManager : MonoBehaviour
{
public PlayerData PlayerData;
public PlayerData AIEnemyData;
public MapData MapData;
public void Load()
{
object loadedPlayerData = null;
object loadedEnemyData = null;
object loadedMapData = null;
//
// <---- load logic ----- >
//
this.PlayerData = (PlayerData) loadedPlayerData;
this.AIEnemyData = (PlayerData) loadedEnemyData;
this.MapData = (MapData) loadedMapData;
}
}
[System.Serializable]
public class PlayerData
{
public int Health;
public int Experience;
public int TimeSaved;
public long LastSaveDateTimeTicks;
public string PlayerName;
public string CharacterName;
public List<int> UnitTypesRecruited;
public List<int> UnitTypesActive;
public int SpaceCredits;
public List<int> AchievementProgress;
}
[System.Serializable]
public class MapData
{
public List<int> LocationIndicesExplored;
public long CurrentStellarDate;
public int StarCount;
public int EnemiesRemaining;
public int SystemType;
public string NameOfSystem;
public long SizeOfSystem;
}
Now you can store and load lots of MapData and even store them in List fields in the manager, and the same with multiple PlayerData objects for multiplayer or multiple AI opponents in a 4x game, for example. In this manner you can just access the loaded values by accessing the playerdata itself, etc.
Right now this uses a lot of public values, but I advise keeping as much private as possible for encapsulation. Also I would recommend having the data be separate scripts so they can expand without bloating the management script.
O$$anonymous$$ sounds good, but ...
I have to declare a variable in the serializable class, so that I can save/load that variable, yes?
But that declaration inside a serializable class (even if the variable and serializable class are both public) does not seem to count towards making that variable available as a public variable within the project or even within the same script in which I declare the serializable class ... so I have to declare it again outside the serializable class ... so, there's the duplicate declarations that I don't know how to avoid.
What am I missing here? :\
Yes, you do have to have fields in the class you are going to serialize; it's what will be written to file.
When you load that file it creates a new instance of that class, with populated fields. $$anonymous$$eaning, after you cast the loaded object to the appropriate class, you can access those public variables like you could any other class in your project.
Because you can access them, you can ins$$anonymous$$d just store the whole loaded class as a "container", if you must. I've expanded the answer to include an example.
O$$anonymous$$, that looks perfect, exactly what I was hoping for, thank you! Now to go make it work, if I am smart enough. But it looks so good I will accept this answer just on spec. Cheers & thanks!
Geig has a public class GameControl { } with some variables declared.
Then he has a [SERIALIZABLE] class PlayerData { } with the same variables declared again.
$$anonymous$$aybe I am supposed to be combining the two? Could we e.g. serialize the public class GameControl? and do away with the PlayerData class?
... I'm gonna have to try it, aren't I ... at least it's an idea to try ... brb ...
You can't serialize game control because it's a monobehaviour.
(in my best Sam Lowry voice) ... $$anonymous$$y God, it works!
Your answer
![](https://koobas.hobune.stream/wayback/20220612081519im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
[CLOSED]Problem with serialization after PUN update 2 Answers
Cannot read past end of stream, MemoryStream 1 Answer
TextAsset thinks file is ~6856 bytes when it is 120123 bytes 0 Answers
Cant save/load game data 2 Answers
How to serialize a List of ContentPacks (from Morph3D) in Photon Unity Networking? 0 Answers