How to save multiple instances of the same class

How would I go about saving my game?

I´d like to point out I´m pretty new to Unity and coding in general, so I may not be familiar with all the terms. I´m not looking for you to code my game, but rather point me to the right direction.

I´m making a game where the player is a shopkeeper. The game is going to be an idle game, where you naturally need to save your progress. There is 75 different items and 200 different customers. All the items and customers are created in the inspector. There is an item-script, which I attach to all the items (hammer, axe, sword etc). In the script there is a class that contains values like quantity of said item in the shop and current price of the item. Those values are modified by the player via UI buttons in-game. The items differ from each other by the values I assign to them via the inspector. Those values are the likes of damage of the item and the base value of “need” the item puts out.

The customers don´t need to be created in the inspector, since they all are alike. They just have random values (personalities) and needs for the items. The personalities are created randomly at the start of the game. But when you start the game the second time, the personalities are loaded from a file (the personalities may change a little based on your actions). Same goes for the needs. I know it´s going to be a lot of work, but I´m planning to make the need system values like needHammer, needAxe, needSword etc. This also makes it so that I don´t have to refer to other classes, since I understand that makes saving a wee bit harder. So every customer has a customer-script with a class that holds the personality values and the need values. Nothing needs to be assigned in the inspector.

The game is going to be saved locally on the phone/pc. I don´t want to use playerprefs, even I know not to use that. I have looked into binary serialization, XML serialization and some different saving assets, but I´m not sure which way to go. I´ve read something about XML being able to support lists of classes, which might be good for this situation?

I have also gone through a lot of questions here related to this question but most of the answers just go “Look into Binary formatting”, totally overlooking the fact that this would make potentially hundreds of save files. So one more thing is that I would prefer that saving the game could make as little files as possible. I think I would know how to do this using binary serialization, but to my understanding my method would create 75 save files for items and another 200 files for the customers. That is less than ideal.

As I said, I´m pretty new to making games, but trust me, this game is not going to be as complicated as it might seem.

Thanks a lot in advance.

I think you should look into Json serialization. I also advise you to look into how you are storing your data.
Games leverage all sorts of different technologies when tackling these challenges. You should be asking yourself a few questions:

  • What data is important and unique?
  • Can my data be reconstructed from more basic values?
  • Does my save system need to be portable between games?
  • Will I store my user’s saved games online or locally to their device?
  • Do I want to support multiple saved files?
  • How do I save files for multiple users?
  • What does a frame state of my game look like?
  • Does my game have a natural state where a save makes sense?

Obviously this list could go on for a bit, but this is how you should be thinking about the task.

For some extra info on a couple of the above points. Data reconstruction is an important skill to understand and master. An example could be how you store a sword item:

// SowrdData
public class SwordData {
	string name;
	int cost;
	string imagePath;
	float damage;
	float durability;
	
	public SwordData(){
		
	}
}

// SwordData as a json:
{
	"name":"Excalibur",
	"cost":5000,
	"imagePath":"UI\Swords\Excalibur",
	"damage":1200.0,
	"durability":12
}

// You can save space by constructing the image path from name when the item is loaded
{
	"name":"Excalibur",
	"cost":5000,
	"damage":1200.0,
	"durability":12
}

// If your names and images are not 1 to 1 you can go the imageId route and store the id in the data
{
	"name":"Excalibur",
	"cost":5000,
    "imageId":1002,
	"damage":1200.0,
	"durability":12
}

//by not storing the image path you save 19 x 4 bytes = 76 bytes

//Cases like this is why most games use local databases to store item stats and tie them to integers or fixed length ids.

//You can also save an entire inventory of swords in one string via json it would look sorta like this:

"shop_inventory":[
{
	"name":"Excalibur",
	"cost":5000,
	"damage":1200.0,
	"durability":12
},
{
	"name":"Excalibur",
	"cost":5000,
	"damage":1200.0,
	"durability":12
},
{
	"name":"Excalibur",
	"cost":5000,
	"damage":1200.0,
	"durability":12
},
{
	"name":"Excalibur",
	"cost":5000,
	"damage":1200.0,
	"durability":12
},
{
	"name":"Excalibur",
	"cost":5000,
	"damage":1200.0,
	"durability":12
}]

But yeah, look into Json, it is an easy beginner way to store data. If you search for “Json .Net” in the asset store the package by ParentElement, LLC is very good and easy to use:

// convert the array of swords into json then write it to a file
string outData = JsonConvert.Serialize(shopInventory);
File.Write(outData);


// Then you would read the string from the file into "shopData" and then convert it back into shopInventory
Sword[] shopInventory = JsonConvert.Deserialize<Sword[]>(shopData);

Here’s a link to a great tutorial I used to add data saving to my games:

You don’t need to create hundreds of save files with a Binary Formatter. What I did was I had lists of classes (List, List), which I would use a Binary Formatter to save to a single file.

Thanks a lot for the answers guys! I looked into JSON and it definitely looks like it would be easiest, since I can just dump my data there. StewVanB thanks for the thorough answer but it seems like I may have explained this wrong. I have actually changed this shopkeeping thing from swords and such to basic shop items like apples and oranges. This might also help you understand that this game is more about the numbers than the attributes of the items.

Answers to your questions StewVanB: all instances of Item and Customer will have important and unique values. All values are either strings, floats or ints. I´m planning on a local idle game, so there is going to be just one local save file used by one player. At minimum the game would save the needed data when the game is closed.

So I´ll start this over a little and I´ll copy the code I have tried. I have an Item prefab. I have put two Items to the scene and named them Apple and Orange. The Item Prefab has scripts called Item, ItemData and Buttons.

For now the Item scripts goes like this. It is going to have a lot more in the future. I will assign the itemData in the inspector.

public class Item : MonoBehaviour
{
    public ItemData itemData;
    string dataPath; 

    private void Start()
    {
        itemData = GetComponent<ItemData>();
        dataPath = Path.Combine(Application.persistentDataPath, "ItemData.txt");
        Debug.Log(Application.persistentDataPath);
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
            SaveItemData(itemData, dataPath);

        if (Input.GetKeyDown(KeyCode.L))
            LoadItemData(dataPath);
    }

    static void SaveItemData (ItemData data, string path) 
    {
        string jsonString = JsonUtility.ToJson(data);

        using (StreamWriter streamWriter = File.CreateText(path))
        {
            streamWriter.Write(jsonString);
        }
    }

    void LoadItemData (string path) 
    {
        using (StreamReader streamReader = File.OpenText(path))
        {
            string jsonString = streamReader.ReadToEnd();
            JsonUtility.FromJsonOverwrite(jsonString, itemData);
        }
    }

And the ItemData scripts goes like this. ItemData will also have a lot more values in the future. These are just for testing to see if it will work and I will build on that:

public class ItemData : MonoBehaviour
{
    public int shopAmount; 
    public float currentPrice;
}

I will then put Apple in the Apple Gameobject´s ItemData in the inspector. And same thing for Orange.

There are UI elements; Buttons, that you press so you can buy more Apples to the store or rise the asking price of said Apple. Im not going to copy the Buttons script here, but it is going to modify ItemData and the Gameobject Apple is going to be put in the Buttons-scripts ItemData in the inspector.

This goes just great, I modify the values with the buttons in-game, so that Apple has quantity of 10 and price of 10. Orange has quantity of 20 and price of 20. Then I save the game and rise the values for Apple to 15/15 and Orange to 25/25. I press Load and boom. Apple and Orange both have values of 10/10. The ItemData.txt has just one string that goes like this:
{“shopAmount”:10,“currentPrice”:10}

And I was hoping for two strings, to each it´s own.

Rugbug_Redfern I think the Binary formatter list solution would work but it would make me do a LOT of work. I understood it so that there has to be lists for every value. But since my Customers will have about 80 values, it would be a lot easier to just dump it all to a Json string, if that would be possible. Furthermore I think I don´t need the info to be non-readable. If I can do it like this in Json, I will.

So the question is: is my whole design critically flawed? Is saving doable like this?