I'm trying to create a little clicker game with unity and now I need to save Shop's items in a binary file. The below code is my Shop class which is called when I click on the button icon, I need to check if the shop data exists in my save file before loading the shop and if exists replace the default list with the saved one, example: The first time I click on the shop the game should save every shop item available with cost, name, image and level, when the player buy something the code saves the shop items/changes into the file and when the player opens the shop again it should reload the values from the save file.
I know how to save the info into a file if is just a boolean, int, float, etc but not a list
public class Shop : MonoBehaviour
{
// Singleton Instance
public static Shop Instance = null;
[System.Serializable] public class ShopItem
{
public float costMultiplier;
public string itemName;
public Sprite image;
public float price;
public Button purchase;
public int level;
}
[SerializeField]
public List<ShopItem> shopItemsList;
GameObject ItemTemplate;
GameObject ShopItemObj;
[SerializeField] Transform ShopScrollView;
public GameObject ShopCanvas;
private void Awake()
{
SingletonSetup();
}
private void SingletonSetup()
{
if (Instance == null)
{
Instance = this;
}
else if (Instance != this)
{
Destroy(gameObject);
}
}
private void Start()
{
ItemTemplate = ShopScrollView.GetChild(0).gameObject;
int len = shopItemsList.Count;
GameData data = SaveSystem.LoadData();
for (int i = 0; i < len; i++)
{
ShopItemObj = Instantiate(ItemTemplate, ShopScrollView);
/*if (data.firstRun)
{*/
ShopItemObj.transform.GetChild(0).GetComponent<Image>().sprite = shopItemsList[i].image;
if (shopItemsList[i].level == 0)
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(shopItemsList[i].price, GameController.Instance.scientificNumbers);
}
else
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter((shopItemsList[i].price * shopItemsList[i].costMultiplier), GameController.Instance.scientificNumbers);
}
ShopItemObj.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = shopItemsList[i].itemName;
float price = shopItemsList[i].price;
ShopItemObj.transform.GetChild(3).GetComponent<Button>().onClick.AddListener(() => { OnPuchase(price); });
ShopItemObj.transform.GetChild(4).GetComponent<TextMeshProUGUI>().text = "level: " + shopItemsList[i].level;
/*}
else
{
ShopItemObj.transform.GetChild(0).GetComponent<Image>().sprite = data.shopItemsList[i].image;
if (shopItemsList[i].level == 0)
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(data.shopItemsList[i].price, GameController.Instance.scientificNumbers);
}
else
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter((data.shopItemsList[i].price * data.shopItemsList[i].costMultiplier), GameController.Instance.scientificNumbers);
}
ShopItemObj.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = data.shopItemsList[i].itemName;
float price = data.shopItemsList[i].price;
ShopItemObj.transform.GetChild(3).GetComponent<Button>().onClick.AddListener(() => { OnPuchase(price); });
ShopItemObj.transform.GetChild(4).GetComponent<TextMeshProUGUI>().text = "level: " + data.shopItemsList[i].level;
}*/
}
Destroy(ItemTemplate);
}
private void Update()
{
int len = shopItemsList.Count;
for (int i = 0; i < len; i++)
{
if (!GameController.Instance.CanAffordPurchase(shopItemsList[i].price))
{
ShopItemObj.transform.GetChild(3).GetComponent<Button>().enabled = false;
}
else
{
ShopItemObj.transform.GetChild(3).GetComponent<Button>().enabled = true;
}
}
}
public void OnPuchase(float price)
{
if (GameController.Instance.CanAffordPurchase(price))
{
int len = shopItemsList.Count;
for (int i = 0; i < len; i++)
{
if (shopItemsList[i].level < 1)
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(shopItemsList[i].price, GameController.Instance.scientificNumbers);
GameController.Instance.PurchaseItem(price);
}
else
{
ShopItemObj.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = "$" + GameController.Instance.MoneyConverter(shopItemsList[i].price * shopItemsList[i].costMultiplier, GameController.Instance.scientificNumbers);
shopItemsList[i].price = shopItemsList[i].price * shopItemsList[i].costMultiplier;
GameController.Instance.PurchaseItem(price * shopItemsList[i].costMultiplier);
}
ShopItemObj.transform.GetChild(4).GetComponent<TextMeshProUGUI>().text = "level: " + (shopItemsList[i].level += 1);
}
SaveSystem.SaveData();
}
else
{
Debug.LogError("Cannot affor the item");
}
}
public void HideCanvas()
{
ShopCanvas.gameObject.SetActive(false);
}
public void ShowCanvas()
{
ShopCanvas.gameObject.SetActive(true);
}
}
My GameData.cs:
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[Serializable]
public class GameData
{
public static string saveFileName = "Clicker.unity2d";
public float money;
public bool firstRun;
public bool scientificNumbers;
public List<Shop.ShopItem> shopItemsList;
public GameData()
{
money = GameController.Instance.money;
firstRun = GameController.Instance.firstRun;
scientificNumbers = GameController.Instance.scientificNumbers;
}
}
public static class SaveSystem
{
public static void SaveData()
{
BinaryFormatter formatter = new BinaryFormatter();
string path = Application.persistentDataPath + "/" + GameData.saveFileName;
FileStream stream = new FileStream(path, FileMode.Create);
GameData data = new GameData();
formatter.Serialize(stream, data);
stream.Close();
}
public static GameData LoadData()
{
string path = Application.persistentDataPath + "/" + GameData.saveFileName;
if (File.Exists(path))
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(path, FileMode.Open);
GameData data = formatter.Deserialize(stream) as GameData;
stream.Close();
return data;
}
else
{
return new GameData { firstRun = true };
}
}
}