Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

money system in death menu

Discussion in 'Scripting' started by jbowers74321, Jan 8, 2020.

  1. jbowers74321

    jbowers74321

    Joined:
    Oct 30, 2019
    Posts:
    25
    I followed this tutorial
    and when I click a button the money saves and can be used elsewhere but when I crash in my endless runner and my death menu pops up the score resets why is that? here is my death menu code
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class DeathMenu : MonoBehaviour
    8. {
    9.     public Text scoreText;
    10.     public Image backgroundImg;
    11.     public static int moneyAmount;
    12.  
    13.     private bool isShowned = false;
    14.  
    15.     private float transition = 0.0f;
    16.  
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.         gameObject.SetActive(false);
    21.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    22.     }
    23.  
    24.     // Update is called once per frame
    25.     void Update()
    26.     {
    27.         if (!isShowned)
    28.             return;
    29.  
    30.         transition += Time.deltaTime;
    31.         backgroundImg.color = Color.Lerp(new Color(0, 0, 0, 0), Color.black, transition);
    32.     }
    33.  
    34.     public void ToggleEndMenu(float score)
    35.     {
    36.         gameObject.SetActive(true);
    37.         scoreText.text = ((int)score).ToString();
    38.         isShowned = true;
    39.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    40.  
    41.     }
    42.  
    43.     public void Restart()
    44.     {
    45.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    46.         SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    47.     }
    48.  
    49.     public void ToMenu()
    50.     {
    51.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    52.         SceneManager.LoadScene("Menu");
    53.     }
    54. }
    55.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Assuming the value in question is in the static field called
    moneyAmount
    , I see that you are only ever calling
    PlayerPrefs.SetInt()
    to write it to playerprefs. Is somewhere else loading it from player prefs?

    Also, is anywhere else in your code setting
    moneyAmount
    to zero? Since it is public static, anyone can write it. You can guard it a bit with a construct like this:

    Code (csharp):
    1.     public static int moneyAmount { get; private set;}
    This will trigger compiler errors if anyone else tries to change it outside of this function, but they can still use it.

    However, keep in mind since you never reload it from PlayerPrefs in the code above, next time you run it will be zero, and then your Start() function will instantly write it back to zero in PlayerPrefas.

    Usually the pattern is to have a clear load/save demarcation point so you avoid sprinkling PlayerPrefs calls throughout your code, which can make for this exact error and be more difficult to track down.
     
  3. olejuer

    olejuer

    Joined:
    Dec 1, 2014
    Posts:
    210
    Well in your script you have a field called moneyAmount that you store in the PlayerPrefs at several places, but you never read from the PlayerPrefs. The field moneyAmount is never set and will remain at a default value of zero. It must be that you set this field from outside the script, which makes this a bit hard to understand. I am not clear about how this script integrates with the rest of your code base.

    You should probably only write to PlayerPrefs when you close the game and read from it on start up. It is a permanent storage that is meant to hold data between sessions. It is not intended to be used frequently during the game.
     
  4. jbowers74321

    jbowers74321

    Joined:
    Oct 30, 2019
    Posts:
    25
    this is the script where i pick up coins
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class GameControlScript : MonoBehaviour {
    8.  
    9.     public Text moneyText;
    10.     public static int moneyAmount;
    11.     int isDesertSold;
    12.  
    13.     // Use this for initialization
    14.     void Start () {
    15.         moneyAmount = PlayerPrefs.GetInt ("MoneyAmount");
    16.         isDesertSold = PlayerPrefs.GetInt("IsDesertSold");
    17.     }
    18.    
    19.     // Update is called once per frame
    20.     void Update () {
    21.         moneyText.text = "" + moneyAmount.ToString() + "$";
    22.     }
    23.  
    24.     public void gotoShop()
    25.     {
    26.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    27.         SceneManager.LoadScene("LevelSelect");
    28.     }
    29. }
    30.  
    and once i press the button to go to shop the money amount is there this is my shop code
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5. using UnityEngine.UI;
    6. using System.Runtime.Serialization.Formatters.Binary;
    7. using System.IO;
    8. using System;
    9.  
    10. public class ShopControl : MonoBehaviour
    11. {
    12.  
    13.     public static int moneyAmount;
    14.     int isDesertSold;
    15.  
    16.     public Text moneyAmountText;
    17.     public Text desertPrice;
    18.  
    19.     public Button buyButtonDesert;
    20.  
    21.     // Start is called before the first frame update
    22.     void Start()
    23.     {
    24.         moneyAmount = PlayerPrefs.GetInt("MoneyAmount");
    25.     }
    26.  
    27.  
    28.     // Update is called once per frame
    29.     void Update()
    30.     {
    31.         moneyAmountText.text = "" + moneyAmount.ToString() + "$";
    32.  
    33.         isDesertSold = PlayerPrefs.GetInt("IsDesertSold");
    34.  
    35.         if (moneyAmount >= 5 && isDesertSold == 0)
    36.             buyButtonDesert.interactable = true;
    37.         else
    38.             buyButtonDesert.interactable = false;
    39.     }
    40.  
    41.     public void buyDesert()
    42.     {
    43.         moneyAmount -= 5;
    44.         PlayerPrefs.SetInt("IsDesertSold", 1);
    45.         desertPrice.text = "";
    46.         buyButtonDesert.gameObject.SetActive(false);
    47.     }
    48.  
    49.     public void ToForest()
    50.     {
    51.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    52.         SceneManager.LoadScene("motomadness");
    53.     }
    54.  
    55.     public void ToCity()
    56.     {
    57.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    58.         SceneManager.LoadScene("City");
    59.     }
    60.  
    61.     public void ToDesert()
    62.     {
    63.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    64.         SceneManager.LoadScene("Desert");
    65.     }
    66.  
    67.     public void ToWinter()
    68.     {
    69.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    70.         SceneManager.LoadScene("Winter");
    71.     }
    72.  
    73.     public void ToDungeon()
    74.     {
    75.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    76.         SceneManager.LoadScene("Dungeon");
    77.     }
    78.  
    79.     public void ToMenu()
    80.     {
    81.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    82.         SceneManager.LoadScene("Menu");
    83.     }
    84. }
    85.  
    and it seems when i press the button to go to the menu it resets to zero as well why does it save for the shop but not for anything else this is my main menu code
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5. using UnityEngine.UI;
    6.  
    7. public class MainMenu : MonoBehaviour
    8. {
    9.     public Text highscoreText;
    10.     public Text moneyAmountText;
    11.     public static int moneyAmount;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         highscoreText.text = "Highscore : " + ((int)PlayerPrefs.GetFloat("Highscore1motomadness")).ToString();
    17.         PlayerPrefs.GetInt("MoneyAmount", moneyAmount);
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         moneyAmountText.text = "" + moneyAmount.ToString() + "$";
    24.     }
    25.  
    26.     public void ToGame()
    27.     {
    28.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    29.         SceneManager.LoadScene("motomadness");
    30.     }
    31.  
    32.     public void ToMenu()
    33.     {
    34.         PlayerPrefs.SetInt("MoneyAmount", moneyAmount);
    35.         SceneManager.LoadScene("LevelSelect");
    36.     }
    37. }
    38.  
     
  5. olejuer

    olejuer

    Joined:
    Dec 1, 2014
    Posts:
    210
    Again, during your game, do not use PlayerPrefs. Only do that on the very beginning and end. During the game, use a regular property. Have only one of those. Currently all your scripts have their own moneyAmount variable and they could be different. It is much easier to have one script that controls the money and all other scripts can reference it.

    I think you probably call PlayerPrefs.SetInt somewhere before you load from it or update the moneyAmount variable in that script. At that time, moneyAmount is still zero and resets your balance.
     
  6. olejuer

    olejuer

    Joined:
    Dec 1, 2014
    Posts:
    210
    Think of PlayerPrefs like a safe where you put things while you don't use them. The script that holds moneyAmount is your wallet. Currently you have at least three of those and all of them constantly mess around with your safe.
    Ever watched three people mess around with a safe full of money? Yeah, it's empty in the end :D
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,971
    Exactly this. Establish a clear point where the saved value is loaded from PlayerPrefs (the safe) into a variable, as well as a point (or points) where it needs to be saved back into PlayerPrefs (the safe), such as when a level is over.

    Write out a diagram if you need to, such as:

    first scene - load the data
    game over scene - save the data

    That can help you visualize when in time everything should happen. During the game, you would ONLY change the variable, and never touch PlayerPrefs (the safe).
     
  8. VSM2018

    VSM2018

    Joined:
    Jun 14, 2018
    Posts:
    16
    I suggest going through the tutorial again. It seems you have some mistakes in your code. In first posted script you SetInt in your start method. I think it should be GetInt. Also you have assigned public static int moneyAmount in all of your scripts.
     
    Kurt-Dekker likes this.
  9. jbowers74321

    jbowers74321

    Joined:
    Oct 30, 2019
    Posts:
    25
    I am a beginner but when I remove public static in moneyAmount in one of the scripts I get a bunch of errors saying that moneyAmount doesn't exist in the current context and if I remove PlayerPrefs.SetInt("MoneyAmount", moneyAmount); from any of my scripts for buttons it doesn't save the coins in the next scene I have changed SetInt to GetInt in my death menu script and it loads the previous coins I had saved but when I collect more coins and die it resets back to the previous coins I had before I started the level. can anyone give me an example or something to help me understand a little more?
     
  10. jbowers74321

    jbowers74321

    Joined:
    Oct 30, 2019
    Posts:
    25
    it also seems weird that if I have a button on the level scene, collect coins, die and press the button on the level scene it saves my coins but if I die and then press a button on the death menu it doesn't save my coins.
     
  11. olejuer

    olejuer

    Joined:
    Dec 1, 2014
    Posts:
    210
    First, remove all your GetInt and SetInt calls. You do not need PlayerPrefs. Those are ONLY interesting if you want to keep state after closing your game so taht you can continue, when you start it again. You are having much more basic issues to solve before that. Keep that for later.

    Delete all variables called "moneyAmount", but one. Then, from the places where you deleted it, you access it with ClassName.moneyAmount, where ClassName is the name of the class that still has the field. It is a static variable after all. Read up on that keyword "static".

    You could add Debug.Log statements at various positions and print out the state that is confusing you to track down where it behaves differently than you would expect. This way you can get to the bottom of your problem. Better even use the debugger and step through your code with it.