Saving an array?

I’ve been following Flarvain’s tutorial on how to make a shop system in unity.
(1) Shop Tutorial Unity - [2021] - YouTube.
(1) Shop Tutorial Unity #2 [2021] - Scriptable Objects - YouTube
(1) Shop Tutorial Unity #3 [2021] - Handling Purchases - YouTube.
I am a little in over my head as you could tell, but I want to expand on the shop system by letting the player display the purchased item on the main screen once the purchase has been made. I’ve managed to get the button to behave in the way that I need, however I don’t understand how to save the changes.
I’ve used PlayerPrefs in a separate script to save the currency with which the player has to buy their items. But that doesn’t seem to work here.

Any and all help apprecitated:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class WardrobeManager : MonoBehaviour
{
    [Header("Panel")]
    public GameObject wardrobePanel;
    public GameObject[] wardrobePanelTwo;
    public WardrobeTemplate[] wardrobeTemplate;
    public CollectableItem[] collectableItem;
    public Button[] buyButton;
    public Button[] ondisplayButton;
    public GameObject[] buyHolder;
    public GameObject[] ondisplayHolder;
    public Image[] displayedItem;
    private CoinsManager coinsManager;
    private string wardrobekey = "Put On Display";
    //bool buybuttonClicked = false;

    // Start is called before the first frame update
    void Start()
    {
        coinsManager = FindObjectOfType<CoinsManager>();
        for (int i = 0; i < collectableItem.Length; i++)
        {
            wardrobePanelTwo[i].SetActive(true);
            ondisplayHolder[i].SetActive(false);
        }
        LoadPanel();                   
    }

    public void OpenPanel()
    {
        wardrobePanel.SetActive(true);
    }

    public void ClosePanel()
    {
        wardrobePanel.SetActive(false);
    }

    // Update is called once per frame
    void Update()
    {
        CheckPurchaseable();
    }

    public void CheckPurchaseable()
    {
        for (int i = 0; i < collectableItem.Length; i++)
        {
            if (coinsManager.coins >= collectableItem[i].price)
            {
                buyHolder[i].SetActive(true);
                buyButton[i].interactable = true;
            }
            else
            {
                buyHolder[i].SetActive(true);
                buyButton[i].interactable = false;
            }
        }
    }

    public void PurchaseCollectable(int btnNo)
    {
        if (coinsManager.coins >= collectableItem[btnNo].price)
        {
            coinsManager.coins = coinsManager.coins - collectableItem[btnNo].price;
            coinsManager.coinsUI.text = coinsManager.coins.ToString();
            buyHolder[btnNo].SetActive(false);
            CheckPurchaseable();
        }
        ondisplayHolder[btnNo].SetActive(true);
    }

    public void LoadPanel()
    {
        for (int i = 0; i < collectableItem.Length; i++)
        {
            wardrobeTemplate[i].titleTxt.text = collectableItem[i].title;
            wardrobeTemplate[i].priceTxt.text = collectableItem[i].price.ToString();
        }
    }
}

PlayerPrefs is useful for onesies and twosies, but beyond that it gets very awkward.

A more generalized solution is to store your data in an instance of a class, perhaps with arrays or other class instances inside of it, and use something like JSON to serialize the data into a string, then write that string to a file.

Reading the string back, you can use JSON to “reinstate” the former object the next time you run the game. This is the basic mechanism of any load/save system in any game.

Notes on Load/Save:

https://discussions.unity.com/t/799896/4

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.

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.

https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide

1 Like

Thank you!