- Home /
How can I make the LoadPlayerName() work in this script using JsonUtility? (or am I even going about this the right way)
Hey and thanks in advance for any help! Let me start by saying I have no clue what I'm doing and exhaustive research and trial and error have made a little progress but mostly added to confusion.
I've made it all the way through Unity Essentials and this is the last step before finishing the Junior Programmer: Manage scene flow and data mission in same Pathway and I'm a little stuck so figured I would ask my 1st question on here. It's in regards to the Submission: Data persistence in a new repo.
I have commented most of my questions/ issues in the script below for any interested in helping me understand what I am doing wrong but the main thing that has me stuck is:
How do I make the LoadPlayerName() actually return the playerNameInput at Start() if playerNameInput == null using JsonUtility to read it from an already created file?
(As in Player loads app Enters name on Menu, Player starts game, Name saves to file, Player goes back to Menu, name loads to text display showing last player, if no new PlayerNameInput, then it loads previously entered name to display in game when going back to main scene)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using System.IO;
#if UNITY_EDITOR
using UnityEditor;
#endif
[DefaultExecutionOrder(1000)] //Executes all default scripts 1st before loading this one (Helpful for UI)
public class MenuUIHandler : MonoBehaviour
//class goal: To control all Menu Options(done), Save PlayerNameInput between scenes, & Save Last PlayerNameInput & Highscores between sessions(Will add score variables after I figure out save/load).
{
public InputField playerNameInput;
public static string playerNameStr;
public Text playerNameDisplay;
private void Start()
{
//playerNameDisplay.text = playerNameStr; //Disabled to test LoadPlayerName().
LoadPlayerName(); //Trying to use this to load the last playerNameInput that was saved to JSON file if (playerNameInput == null). Not Working!
}
public void StartNew()
{
SceneManager.LoadScene(1);
LoadPlayerName();
//This works to hold the playername from scene to scene to scene but can't change it unless session restart.
/* if (playerNameStr == null)
{
Debug.Log("Player Name is: " + playerNameInput.text);
playerNameStr = playerNameInput.text;
} */
//This works to save playerNameInput from menu>main>menu scenes but doesn't hold after StartNew() if no playerNameInput.
/*if (playerNameInput != null)
{
Debug.Log("Player Name is: " + playerNameInput.text);
playerNameStr = playerNameInput.text;
}
else if (playerNameInput == null)
{
//LoadPlayerName();
}*/ //Disabled to test LoadPlayerName on Start().
}
public void BackToMenu()
{
SceneManager.LoadScene(0);
}
public void Exit()
{
SavePlayerName();
#if UNITY_EDITOR
EditorApplication.ExitPlaymode();
#else
Application.Quit();
#endif
}
[System.Serializable]
class SaveData
{
//Added these 2 to test if saves
public InputField playerNameInput; //Saves but always with InstanceID: 0. Probably pointless and will remove if proven.
public /*static*/ string playerNameStr; //This 1 doesn't save, assuming because static? Correct & it seems to work the same without static so may remove later.
public Text playerNameDisplay; //Saves with instanceID: 94418 (assuming saves correctly but doesn't load correctly on Start(), only after StartNew()) Don't think correct, was just loading playerNameDisplay.
}
public void SavePlayerName()
{
SaveData data = new SaveData();
//data.playerNameDisplay = playerNameDisplay; //Going to try using playerNameStr instead.
data.playerNameStr = playerNameStr; //This populates save file with string of correct name entered.
string json = JsonUtility.ToJson(data);
File.WriteAllText(Application.persistentDataPath + "/savefile.json", json);
//Display on console what is being saved
Debug.Log("SavePlayerName saved " + playerNameDisplay.text);
}
public void LoadPlayerName() //This is what I'm trying to get working.***
{
string path = Application.persistentDataPath + "/savefile.json";
if (File.Exists(path))
{
string json = File.ReadAllText(path);
SaveData data = JsonUtility.FromJson<SaveData>(json);
//data.playerNameDisplay = playerNameDisplay; //This seems to work but doesn't load data at startup.
playerNameStr = data.playerNameStr; //This should be right but doesn't load saved data at Start() either.
Debug.Log("LoadPlayerName worked & loaded data: " + playerNameDisplay.text); //Displays right text but not sure its actual text from save file or just playerNameInput.
}
}
public void LastPlayer() //Thought about using this to load last playerNameInput entered but don't know what I'm doing so haven't called it anywhere yet.
{
string path = Application.persistentDataPath + "/savefile.json";
if (playerNameStr == null)
{
string json = File.ReadAllText(path);
SaveData data = JsonUtility.FromJson<SaveData>(json);
playerNameStr = data.playerNameDisplay.text;
Debug.Log("LastPlayer() called");
}
}
}
Answer by berkun5 · Aug 09, 2021 at 12:31 PM
@CaligoArts playerNameStr = data.playerNameStr; //This should be right but doesn't load saved data at Start() either.
Are you assigning the playerNameStr to an any UI object.text? Try Debug.Log(playerNameStr); right after loading it and see if you can get the correct information on the console. If yes, it seems that you are inserting the data to the string(playerNameStr) but then you need to assign this string to a text field on the UI.
But anyway you can just create a class for this and other related settings,
public class StartSettings
{
public string Name;
public bool soundOn; //you can store any parameters for example
}
public StartSettings mySettings;
void FillClass() //Call this after setting the new name or any other settings that you want to set
{
mySettings.Name = "MyName"; //this = string is your Inputfield.text
mySettings.soundOn = true;
SaveClass(); //save it after modifying your class.
}
void SaveClass()
{
string json = JsonUtility.ToJson(mySettings); //converting the class to a json
**//save json to anywhere you want.**
}
void GetClass() //you can call this at start
{
**//load the json back from whichever path**
string json = File.ReadAllText(path);
mySettings = JsonUtility.FromJson<StartSettings>(json); //inserting json parameters back into the class
Debug.Log(mySettings.Name);
mySettings.Name = myUiObject.text; //this is what you are missing I guess.
}
@berkun5 Thanks for the reply and yes I have an Input field and text display GameObject on the menu scene that works to accept the player name input and display it to the text display. It saves and successfully carries over to the Text Display GameObject on the main game scene and still displays when going back to the Menu scene so that part works but where it breaks is if I don't re-enter the player input once back on the menu then it doesn't carry back over to the game scene when I hit the StartNew(). It just shows blank. So my assumption is that it's not loading the save data correctly from JSON file or I'm not using the correct if() function to call it correctly. I opened the JSON save file and it does save the playerNameStr correctly on Exit() but it will not load that data on next session start. I commented most of that functionality out to disable it so I could focus on testing the LoadPlayerName() to make sure I could get it to load from JSON file. Maybe I am targeting the wrong GameObject if you think the code inside the LoadPlayerName() is correct? So I am working to get a better understanding of how the JsonUtility loads the data back. I'm getting ready for work now so I will go through line by line on the scripting when I get home to understand what you mean a little better. Thanks again!
@CaligoArts Hi again, I tested this myself and it works. I don't have much time to explain but just test this script by assigning an input field and a button to call the saved name. To make it automated just call the GetClass() at the start or awake. You should probably add an if statement where it checks whether the file at the path exists or not.
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
public class HandleJson : MonoBehaviour
{
public StartSettings mySettings = new StartSettings();
public InputField NameInput;
public Button displayName;
private void Start()
{
NameInput.onValueChanged.AddListener(delegate { FillClass(); });
displayName.onClick.AddListener(GetClass);
}
public class StartSettings
{
public string Name;
}
public void FillClass()
{
mySettings.Name=NameInput.text;
Debug.Log(mySettings.Name);
string json = JsonUtility.ToJson(mySettings);
Debug.Log(json);
File.WriteAllText(Application.persistentDataPath + "/savefile.json", json);
}
public void GetClass()
{
string path = Application.persistentDataPath + "/savefile.json";
string result = File.ReadAllText(path);
Debug.Log(result);
mySettings = JsonUtility.FromJson<StartSettings>(result);
NameInput.text = mySettings.Name;
}
}
@berkun5 Hey thanks again for the help! I wasn't really looking for someone to do the work for me. I was looking for a better understanding of how it works but I understand the time constraints and the script you provided should give me a solid example of how it's done so I can work through it and figure it out to see where I was going wrong. This should help a lot so I can stop worrying if the code is right and start focusing on applying the functions correctly. Consider this solved for now and hopefully I can make my next question more specific if I have any. Thanks again, I really do appreciate your time!
Your answer
Follow this Question
Related Questions
Keeping track of time after calling Application.LoadLevel 1 Answer
Most convenient and fast way to persist/access/modify many values from scene to scene? (C#) 0 Answers
Getting "Failed to Unpersist" Errors that are Destroying my Scenes! 1 Answer
Best way to save data 1 Answer
How to make Unity remember purchases made by players using Firebase? 0 Answers