How can i save the data of multiple scripts in a single file?

Just a simple question, i’d appreciate if someone could help me.

I’m coding a save system and can only make it work if i make a save file for the data of each script, it didn’t bother me untill now, but it looks just too amateurish.

So how can i save data from multiple scripts into a single file? Take, for example, the score from the “score script”, all the separated mechanics and store it in a single file, regardless of the file format.

I’ve been advised to take all variables across the multiple scripts and write it in a single file, then i’d call each one from the other scripts that have the actual coding, but i’m not sure if this is the best way.

Thanks in advance :slight_smile:

See step 2 here:

Load/Save steps:

Don’t use the binary formatter/serializer: it is insecure, it cannot be made secure, and it makes debugging very difficult, plus it actually will NOT prevent people from modifying your save data on their computers.

When loading, you can never re-create a MonoBehaviour or ScriptableObject instance directly from JSON. The reason is they are hybrid C# and native engine objects, and when the JSON package calls new to make one, it cannot make the native engine portion of the object.

Instead you must first create the MonoBehaviour using AddComponent() on a GameObject instance, or use ScriptableObject.CreateInstance() to make your SO, then use the appropriate JSON “populate object” call to fill in its public fields.

1 Like

This information about binaryformatter is interesting, i always see people saying that it’s a really safe way to store data. I’ll take a look at that.

I’ve read the thread you linked, and although really insightful, i don’t think it solves my problem. Maybe i misunderstood something?

I know how to handle the data, store and get it back, my problem is that each script - not each variable like the guy from the thread - is getting their own save file. For example: the “score script” would write and read in the “save1” file, the “player script” would do the same for the “save2” file.

I would like to somehow save all of these values, across all scripts, in a single “save” file.
For what i’ve seen so far, maybe it’s not even possible?

I’m a week trying to get this to work, so i’m really tired and i apologize if i just couldn’t grasp something obvious.

Interfaces can help here. For instance things that can contribute to a savegame could express an interface such as ILoadSaveable.

The API for something like that would roughly be something like:

public interface ILoadSaveable
{
  void SaveYourData( DataObject data);
  void LoadYourData( DataObject data);
}

Every MonoBehaviour in your scene that had save-able data would express that interface.

At save time you would do a GetComponent() to get every script, iterate it and ask “is this an ILoadSaveable?” and if so, you would call the SaveYourData(); method.

That method would be different for each script.

The DataObject would express methods to accept and provide saved / loaded data.

This is only part of the problem because obviously at load time, as I pointed out above, the MonoBehaviors have to already exist in scene, so you need some plumbing outside of this, some kind of meta save that tells what scene to load, etc.

But this is a generalized solution that can be built out fully and expanded upon.

Dynamically-created objects would need more: you would need to tell the dynamic components “Hey for this load game, there were 27 zombies, make them, and when you make them I will provide their saved data.”

Saving everything is extremely hairy and almost NEVER done. Save only what you need.

1 Like

I figured out a simple way to just get things going for now, it surely can be improved upon. I’ll write it here to anyone with a similar problem that may find this post through a Google search in the future.

Step 1.

Make a Data script to store all the data that needs to be saved.

Ex:

[System.Serializable]
public class GameData
{

   //Player

   public float saveHealth;
   public float saveSpeed;

   //Score

   public int saveScore;

   //etc

}

Step 2:

Create a method in this same script to assign the actual value from all your other scripts in a instance of this one.

Ex:

public static void GetValues(Gamedata data)
{
   //Player

   data.saveHealth = Player.health;
   data.saveSpeed = Player.speed;

   //Score

   data.saveScore = Score.score;

   /etc
}

Step 3:

Save it to a file with your save system.

Ex:

public static void SaveToFile(GameData data)
{

   GetValues(data);
   SaveSystem.SaveData(data);

}

Step 4:

Select a script, or make a new one. This script will create a new instance of GameData and call GameData.SaveToFile(GameData data)

After that you’ll just need to load the respective data in each script like you would normally do, but now everything will be inside a single file.

1 Like