Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved Saving an array?

Discussion in 'Scripting' started by Cyber_Balls, Sep 30, 2021.

  1. Cyber_Balls

    Cyber_Balls

    Joined:
    Jan 12, 2021
    Posts:
    3
    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:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using TMPro;
    6.  
    7. public class WardrobeManager : MonoBehaviour
    8. {
    9.     [Header("Panel")]
    10.     public GameObject wardrobePanel;
    11.     public GameObject[] wardrobePanelTwo;
    12.     public WardrobeTemplate[] wardrobeTemplate;
    13.     public CollectableItem[] collectableItem;
    14.     public Button[] buyButton;
    15.     public Button[] ondisplayButton;
    16.     public GameObject[] buyHolder;
    17.     public GameObject[] ondisplayHolder;
    18.     public Image[] displayedItem;
    19.     private CoinsManager coinsManager;
    20.     private string wardrobekey = "Put On Display";
    21.     //bool buybuttonClicked = false;
    22.  
    23.     // Start is called before the first frame update
    24.     void Start()
    25.     {
    26.         coinsManager = FindObjectOfType<CoinsManager>();
    27.         for (int i = 0; i < collectableItem.Length; i++)
    28.         {
    29.             wardrobePanelTwo[i].SetActive(true);
    30.             ondisplayHolder[i].SetActive(false);
    31.         }
    32.         LoadPanel();                  
    33.     }
    34.  
    35.     public void OpenPanel()
    36.     {
    37.         wardrobePanel.SetActive(true);
    38.     }
    39.  
    40.     public void ClosePanel()
    41.     {
    42.         wardrobePanel.SetActive(false);
    43.     }
    44.  
    45.     // Update is called once per frame
    46.     void Update()
    47.     {
    48.         CheckPurchaseable();
    49.     }
    50.  
    51.     public void CheckPurchaseable()
    52.     {
    53.         for (int i = 0; i < collectableItem.Length; i++)
    54.         {
    55.             if (coinsManager.coins >= collectableItem[i].price)
    56.             {
    57.                 buyHolder[i].SetActive(true);
    58.                 buyButton[i].interactable = true;
    59.             }
    60.             else
    61.             {
    62.                 buyHolder[i].SetActive(true);
    63.                 buyButton[i].interactable = false;
    64.             }
    65.         }
    66.     }
    67.  
    68.     public void PurchaseCollectable(int btnNo)
    69.     {
    70.         if (coinsManager.coins >= collectableItem[btnNo].price)
    71.         {
    72.             coinsManager.coins = coinsManager.coins - collectableItem[btnNo].price;
    73.             coinsManager.coinsUI.text = coinsManager.coins.ToString();
    74.             buyHolder[btnNo].SetActive(false);
    75.             CheckPurchaseable();
    76.         }
    77.         ondisplayHolder[btnNo].SetActive(true);
    78.     }
    79.  
    80.     public void LoadPanel()
    81.     {
    82.         for (int i = 0; i < collectableItem.Length; i++)
    83.         {
    84.             wardrobeTemplate[i].titleTxt.text = collectableItem[i].title;
    85.             wardrobeTemplate[i].priceTxt.text = collectableItem[i].price.ToString();
    86.         }
    87.     }
    88. }
    89.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,079
    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://forum.unity.com/threads/save-system-questions.930366/#post-6087384

    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<T>() on a GameObject instance, or use ScriptableObject.CreateInstance<T>() 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
     
    Cyber_Balls likes this.
  3. Cyber_Balls

    Cyber_Balls

    Joined:
    Jan 12, 2021
    Posts:
    3
    Thank you!