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

Question Trying to get score data to save into a json file from score script

Discussion in 'Scripting' started by justinmed, Apr 2, 2024.

  1. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    106
    I am trying to get my score in my score script to constantly update into a json file so that I can move onto trying to get it appropriated for a high score system and am just starting small before I move on. However, so far what I have tried just generates a json file with nothing in it. Any tips would be greatly appreciated. You will see that I put in the code that should save the data in the json file in the update part of the script.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.IO;
    5. using Klaviactor.ScoreBoards;
    6. using UnityEngine;
    7. using UnityEngine.UI;
    8. using TMPro;
    9. using UnityEngine.SceneManagement;
    10. using Unity.VisualScripting;
    11.  
    12.  
    13.  
    14. public class Test : MonoBehaviour
    15. {
    16.     public TMP_Text Score;
    17.     public int scoreAmount = 0;
    18.    
    19.    
    20.  
    21.  
    22.  
    23.     // Start is called before the first frame update
    24.     void Start()
    25.    
    26.    
    27.     {
    28.        
    29.         scoreAmount = 0;
    30.         Score = GetComponent<TMP_Text>();
    31.         scoreAmount = PlayerPrefs.GetInt("scoreKey");
    32.        
    33.        
    34.  
    35.  
    36.  
    37.  
    38.  
    39.  
    40.     }
    41.  
    42.  
    43.  
    44.  
    45.     void Update()
    46.  
    47.     {
    48.         string json = JsonUtility.ToJson(Score);
    49.         Debug.Log(json);
    50.  
    51.         using (StreamWriter writer = new StreamWriter(Application.dataPath + Path.AltDirectorySeparatorChar + "ScoreData.json"))
    52.         {
    53.             writer.Write(json);
    54.         }
    55.  
    56.         {
    57.             Score.text = scoreAmount.ToString();
    58.             PlayerPrefs.SetInt("scoreKey", scoreAmount);
    59.         }
    60.     }
    61.        
    62.    
    63.    
    64.  
    65.  
    66.     public void AddScore()
    67.     {
    68.         scoreAmount += 1;
    69.         Score.text = "" + scoreAmount;
    70.        
    71.  
    72.     }
    73.  
    74.    public void SubtractScore()
    75.     {
    76.         scoreAmount -= 1;
    77.     }
    78.  
    79.     public void DeleteScoreKey()
    80.  
    81.     {
    82.        
    83.     }
    84.  
    85.     public void ReturnToMenu()
    86.  
    87.     {
    88.         SceneManager.LoadScene(1);
    89.         PlayerPrefs.DeleteKey("scoreKey");
    90.     }
    91.  
    92.     private void OnApplicationQuit()
    93.     {
    94.         PlayerPrefs.DeleteKey("scoreKey");
    95.     }
    96. }
    97.  
    98.  
    99.    
    100.  
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,240
    I would NOT constantly write to disk. Terrible idea.

    Also you are trying to write a Unity component to disk. Do not do that too as it generally does not work. Use a plain C# object instead.

    StreamWriter stuff is unnecessary in basic situations as well.

    For example:
    Code (CSharp):
    1. [System.Serializable]
    2. public class GameState
    3. {
    4.     public int Score = 0;
    5. }
    6.  
    7. // example code only
    8. GameState state = new GameState()
    9. {
    10.     Score = 100
    11. };
    12.  
    13. string json = JsonUtility.ToJson(state);
    14. path = Application.persistantDataPath + "/Score.txt";
    15. File.WriteAllText(path, json);
    Reading is just File.ReadAllText + Json.FromJson.

    You should only write to disk when you would lose the data, and read it when you need to restore it. For example a singleton game object could read this when it creates itself, an write the value to disk when the application closes. Doesn't need to be any more complicated than that.
     
  3. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,936
    Do you realize that Update is called 60 times a second?
     
  4. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    106
    I kind of see what you are saying and tried implementing that into my own theory into a better light, but it did not work, maybe you could have a look at what I tried from what you showed and see if you notice anything specific. If it saved a score file I could not find it anywhere. I have to update the save pretty much ever click if possible so that when the timer runs out and the script is no longer active I can call on the saved file for high score dictation. I also tried "/Score.json" as well and that did not work either.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.IO;
    5. using Klaviactor.ScoreBoards;
    6. using UnityEngine;
    7. using UnityEngine.UI;
    8. using TMPro;
    9. using UnityEngine.SceneManagement;
    10. using Unity.VisualScripting;
    11.  
    12.  
    13.  
    14. public class Test : MonoBehaviour
    15. {
    16.     public TMP_Text Score;
    17.     public int scoreAmount = 0;
    18.    
    19.     public void SaveToJson()
    20.    
    21.    
    22.     {
    23.         if (Input.GetMouseButtonDown(0)) ;
    24.         {
    25.             SaveToJson();
    26.         }
    27.     }
    28.  
    29.  
    30.     private void Awake()
    31.     {
    32.         Test scoreData = new Test();
    33.         string json = JsonUtility.ToJson(scoreData);
    34.         string path = Application.persistentDataPath + "/Score.txt";
    35.         File.WriteAllText(path, json);
    36.         Debug.Log(path);
    37.     }
     
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,240
    You realise nothing is going to call SaveToJson?

    That whole method makes absolutely no sense.

    Also you should not new() a monobehaviour. Didn't I just tell you not to serialize Unity objects?
     
  6. ArachnidAnimal

    ArachnidAnimal

    Joined:
    Mar 3, 2015
    Posts:
    1,936
    I'm starting to think the OP is just a troll.
     
  7. justinmed

    justinmed

    Joined:
    Dec 19, 2021
    Posts:
    106
    So I figured it out and it was simple, so I had to just use the method as seen below which I added to my Subtract Score and Add Score public void where I created a class that it called on from a string that was designated as System.Serializable and similar to the methods that were similar as suggested by Spiney.

    Here is the code from my score script that is all in the only affected areas.

    Code (CSharp):
    1. public void AddScore()
    2.     {
    3.         scoreAmount += 1;
    4.         Score.text = "" + scoreAmount;
    5.  
    6.         ScoreJSON ScoreNumber = new ScoreJSON();
    7.         ScoreNumber.Amount = Score.text;
    8.  
    9.         string json = JsonUtility.ToJson(ScoreNumber, true);
    10.         File.WriteAllText(Application.dataPath + "/ScoreNumber.json", json);
    11.        
    12.  
    13.  
    14.  
    15.  
    16.     }
    17.  
    18.    public void SubtractScore()
    19.     {
    20.        
    21.         ScoreJSON ScoreNumber = new ScoreJSON();
    22.         ScoreNumber.Amount = Score.text;
    23.  
    24.         string json = JsonUtility.ToJson(ScoreNumber, true);
    25.         File.WriteAllText(Application.dataPath + "/ScoreNumber.json", json);
    26.         scoreAmount -= 1;
    27.     }
    then the separate class file that I had to have in order for it to work.

    Code (CSharp):
    1. [System.Serializable]
    2.  
    3. public class ScoreJSON
    4.  
    5. {
    6.     public string Amount;
    7. }
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    8,240
    You now just have two methods now that do pretty much the same thing. Like I said before you should only read/write to disk when completely necessary. Otherwise during gameplay you can just operate entirely on a score value in memory.

    Could look like this:
    Code (CSharp):
    1. public sealed class ScoreSystem : Monobehaviour
    2. {
    3.     private static ScoreSystem _instance;
    4.    
    5.     private static readonly string _scoreDataPath = $"{Application.persistantDataPath}/Score.txt";
    6.    
    7.     private ScoreData _scoreData;
    8.    
    9.     private void Awake()
    10.     {
    11.         bool exists = File.Exists(_scoreDataPath);
    12.         if (exists == true)
    13.         {
    14.             string json = File.ReadAllText(_scoreDataPath);
    15.             _scoreData = JsonUtility.FromJson(json);
    16.         }
    17.         else
    18.         {
    19.             _scoreData = new ScoreData();
    20.         }
    21.     }
    22.    
    23.     private void OnDestroy()
    24.     {
    25.         string json = JsonUtility.ToJson(_scoreData);
    26.         File.WriteAllText(_scoreDataPath, json);
    27.     }
    28.    
    29.     private static void EnsureSingleton()
    30.     {
    31.         if (_instance == null)
    32.         {
    33.             return;
    34.         }
    35.        
    36.         var gameObject = new GameObject("ScoreSystem");
    37.         _instance = gameObject.AddComponent<ScoreSystem>();
    38.         Object.DontDestroyOnLoad(_instance.gameObject);
    39.     }
    40.    
    41.     public static void ModifyScore(int value)
    42.     {
    43.         EnsureSingleton();
    44.        
    45.         var score = _instance._scoreData;
    46.         score.Score += value;
    47.     }
    48. }
    49.  
    50. [System.Serializable]
    51. public class ScoreData
    52. {
    53.     public int Score;
    54. }
     
    CodeSmile likes this.