I want to save my game data as my 2D game progresses using a DontDestroyOnLoad object.
I have a GameData class/script which stores values like health, magicType, etc, a SaveLoad class/script which saves current values in the GameData class to Json and an empty game object called PlayerData that has both of the above scripts.
Currently, I'm saving values in one scene by using button click events. My object attached to the button is the PlayerData object, and I change values using the GameData script on the click event.
But this only works on the first scene - I can't attach the PlayerData object and store its GameData values because there is no PlayerData object in the editor.
So how can I attach this object, which is in a different scene? Or am I doing this wrong?
Here's a photo of my current project.
Also, when I save a boolean, then open my Json file, the file is empty. Is this normal? Here's my save and load code:
Load:
private string _filePath;
private static DataService _instance;
public DataService Instance
{
get { return _instance; }
}
public GameData _gameData;
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
public void LoadGameData()
{
_filePath = Path.Combine(Application.persistentDataPath, "GameData1.json");
string json;
if (File.Exists(_filePath))
{
json = File.ReadAllText(_filePath);
JsonUtility.FromJsonOverwrite(json, _gameData);
}
else
{
Debug.Log("File missing.");
}
}
Save:
public void SaveGameData1()
{
string json = JsonUtility.ToJson(_gameData);
_filePath = Path.Combine(Application.persistentDataPath, "GameData1.json");
if (File.Exists(_filePath))
{
File.Create(_filePath).Dispose();
}
File.WriteAllText(_filePath,json);
}
EDIT: This is the code of my GameData class:
[Serializable]
public class GameData : MonoBehavior
{
public float Health { get; set; }
}
Data Path
First of all as just recently answered here I wouldn't use the persistentDataPath for development but rather the streamingAssetsPath and on first app run copy the file over.
Singleton Pattern
I see you have the first half of a Singleton pattern but: You never assigned a value to instance. I usually would do it "lazy" in the property or Awake like e.g.
private static DataService instance;
public static DataService Instance
{
if(instance) return instance;
instance = FindObjectOfType<DataService>();
if(instance) return instance;
// If it wasnt found in the scene create it now
instance = new GameObject("DataService", typeof (GameData)). AddComponent<DataService>();
instance._gameData = instance.GetComponent<GameData>();
DontDestroyOnLoad (instance.gameObject);
return instance;
}
private void Awake ()
{
if(instance && instance != this)
{
Debug.LogWarning("Another instance of DataService I already in use");
Destroy(gameObject);
return;
}
if(instance) return;
instance = this;
DontDestroyOnLoad (gameObject);
if(!_gameData) _gameData = GetComponent<GameData>();
}
Or static Class
Actually with the code you provided I doubt that any of your two classes really needs to be a MonoBehaviour!
You could probably simply use something like
public static class DataService
{
private const string FILE_NAME = "GameData1.json";
public static GameData GameData = new GameData();
public static void SaveGameData1()
{
var json = JsonUtility.ToJson(_gameData);
var filePath = Path.Combine(Application.persistentDataPath, FILE_NAME);
if (File.Exists(filePath))
{
File.Create(filePath);
}
File.WriteAllText(filePath,json);
}
public static void LoadGameData()
{
var filePath = Path.Combine(Application.persistentDataPath, FILE_NAME);
if (File.Exists(filePath))
{
var json = File.ReadAllText(_filePath);
JsonUtility.FromJsonOverwrite(json, GameData);
}
else
{
Debug.Log("File missing.");
}
}
}
and
[Serializable]
public class GameData
{
public float SomeValue;
...
}
Now you can from everywhere simply call
DataService.LoadGameData();
And then access value like
DataService.GameData.SomeValue = ...;
For the buttons
I would create a class DataServiceButton which is attached to a UI.Button and registers itself as a listener to onClick like
[RequireComponent(typeof(UI.Button))]
public class DataServiceButton : MonoBehaviour
{
public enum ButtonType
{
Save,
Load
}
// This is set via the Inspector
[SerializeField] private ButtonType type;
// Here you can already reference the according Button component
[SerializeField] private Button button;
private void Awake()
{
if(!button) button = GetComponent<Button>();
// Register as callback
button.onClick.AddListener(HandleClick);
}
private void HandleClick()
{
switch(type)
{
case ButtonType.Load:
DataService.LoadGameData();
// OR IF YOU STICK TO THE SINGLETON
//DataService.Instance.LoadGameData();
break;
case ButtonType.Save:
DataService.SaveGameData();
// OR ACCORDINGLY WITH SINGLETON
//DataService.Instance.SaveGameData();
break;
}
}
}
The question why your file is empty after writing data unfortunately can not be answered without seeing the code of your GameData class...
Make sure your types are serializeable.
Related
[EDIT] Everything is working now! Thank's to #MrMoonMan!
As the title says, I'm working on a mobile game and I just implemented a Check Update popup.
The thing is, the popup is displayed every time the menu scene is loaded, and this is very annoying because if the player goes to the weapon menu and then comes back to the main menu 10 times, he will see the popup 10 times. The goal is to have the popup appear only once per game session, Here is what I tried for the moment but without success:
Using a bool variable
Destroy the gameobject to which the checkupdate script is attached when the user presses the "No Thank's" button
Here is the code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class CheckUpdate : MonoBehaviour
{
public string versionUrl = "";
public string currentVersion;
private string latestVersion;
public GameObject newVersionAvailable;
private static bool hasBeenChecked = false;
void OnAwake()
{
DontDestroyOnLoad(this);
StartCoroutine(LoadTxtData(versionUrl));
}
private IEnumerator LoadTxtData(string url)
{
UnityWebRequest loaded = new UnityWebRequest(url);
loaded.downloadHandler = new DownloadHandlerBuffer();
yield return loaded.SendWebRequest();
latestVersion = loaded.downloadHandler.text;
CheckVersion();
}
private void CheckVersion()
{
Debug.Log("currentVersion = " + currentVersion);
Debug.Log("latestVersion = " + latestVersion);
Version versionDevice = new Version(currentVersion);
Version versionServer = new Version(latestVersion);
int result = versionDevice.CompareTo(versionServer);
if ((latestVersion != "") && (result < 0))
{
newVersionAvailable.SetActive(true);
}
if (GetChecked())
return;
}
public void ClosePopUp(GameObject obj)
{
obj.SetActive(false);
Destroy(this);
}
public void OpenURL(string url)
{
Application.OpenURL(url);
}
public static bool GetChecked()
{
if (hasBeenChecked)
{
return hasBeenChecked;
}
hasBeenChecked = true;
return false;
}
}
EDIT
Ok so you mentioned that it still happens every time the scene is reloaded. That is because the object is created when the scene is loaded. It isn't saved between scenes. To handle that properly you need to tell it to not get destroyed when the scene is unloaded and to do that is simple, and that is by Adding DontDestroyOnAwake. Here is an example of the code:
public class CheckUpdate : MonoBehaviour
{
public string versionUrl = "";
public string currentVersion;
private string latestVersion;
public GameObject newVersionAvailable;
void OnAwake()
{
DontDestroyOnLoad(this);
}
void OnStart()
{
StartCoroutine(LoadTxtData(versionUrl));
}
private IEnumerator LoadTxtData(string url)
{
UnityWebRequest loaded = new UnityWebRequest(url);
loaded.downloadHandler = new DownloadHandlerBuffer();
yield return loaded.SendWebRequest();
latestVersion = loaded.downloadHandler.text;
}
private void CheckVersion()
{
Debug.Log("currentVersion = " + currentVersion);
Debug.Log("latestVersion = " + latestVersion);
Version versionDevice = new Version(currentVersion);
Version versionServer = new Version(latestVersion);
int result = versionDevice.CompareTo(versionServer);
if ((latestVersion != "") && (result < 0))
{
newVersionAvailable.SetActive(true);
}
}
public void ClosePopUp(GameObject obj)
{
obj.SetActive(false);
}
public void OpenURL(string url)
{
Application.OpenURL(url);
}
}
,,Menu scene''? It sound some suspicious. If you load and unload whole new scene as menu, state as bool field in MonoBehaviours or modifing the scene structure (destory, create object) will not work beacuse allways will be loaded new scene from scratch. ;)
If you have to have menu on seperated scene use someting other to manage the state. For example:
DontDestoryOnLoad objects.
Or some C# static class or singleton (not a MonoBehaviour).
So in our visual novel game using the ink/inkle API for unity, I'm trying to implement a save and load system, but I am currently having trouble with loading the saved state the way I intend to.
Based on the API's documentation, to save the state of your story within your game, you call:
string savedJson = _inkStory.state.ToJson();
then to load it:
_inkStory.state.LoadJson(savedJson);
Here is the how I save the current state of the story using PlayerPrefs, which is working just fine.
public void saveGame()
{
DialogueSystem dialogueSystem = GetComponent<DialogueSystem>();
dialogueSystem.savedJson = dialogueSystem.dialogue.state.ToJson();
PlayerPrefs.SetString("saveState", dialogueSystem.savedJson);
Debug.Log(dialogueSystem.savedJson);
}
and here is how I'm trying to load the saved state on Start(), which doesn't load the saved state.
private void Start()
{
dialogue = new Story(dialogueJSON.text);
currentActiveBG = BGs[0];
historyScript = GetComponent<History>();
counterScript = GetComponent<counter>();
if (PlayerPrefs.HasKey("saveState")) { // for loading the saved state
dialogue = new Story(dialogueJSON.text);
savedJson = PlayerPrefs.GetString("saveState");
dialogue.state.LoadJson(savedJson);
loadLine(); //this function contains story.Continue, which loads the next line
Debug.Log(savedJson);
}
else {
loadGame("Pre_Prep1"); // default starting line
}
}
How can I make this work? And is there a better way of implementing this save/load feature?
I'm not sure which game you're going to make but, I use the following saving system in my project and it's working perfectly and you can also use it.
using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Saving System
public class UserData{
#region Save Data Var's
// file Path
private static readonly string FILE_PATH = Application.dataPath +
"/SaveFiles";
public int carToLoad;
public int levelToLoad;
public int unlockLevels;
#endregion
#region Methods
// Save
public static void SaveData(string contents){ // for Car Selection
File.WriteAllText(FILE_PATH + "/UserData.txt",contents);
}
// Load
public static UserData LoadData(){
string _data = File.ReadAllText(FILE_PATH + "/UserData.txt");
return JSONToUserData(_data);
}
// Init
public static void UserData_init(){
CheckFilesPreviousData();
CheckDirectory();
}
// Selection Level Data
public static void SaveData(UserData LevelData) { // for Level
UserData tempObj = LoadData();
tempObj.levelToLoad = LevelData.levelToLoad;
SaveData(UserDataToJSON(tempObj));
}
// UnLock Level Data
public static void SaveUnLockedLevelData(int LevelValue){
UserData tempObj = LoadData();
tempObj.unlockLevels = LevelValue;
File.WriteAllText(FILE_PATH + "/UnLockLevels.text",
UserDataToJSON(tempObj));
}
// Load UnLock Level Data
public static UserData LoadUnLockLevelData(){
string _data= File.ReadAllText(FILE_PATH+"/UnLockLevels.text");
UserData tempObj = JSONToUserData(_data);
return tempObj;
}
#endregion
#region Helper Methods
// !! important
public static UserData JSONToUserData(string path) =>
JsonUtility.FromJson<UserData>(path);// JSON to Obj
public static string UserDataToJSON(UserData obj) => JsonUtility.ToJson(obj);//
Obj to JSON
// Making Directory if not present
private static void CheckDirectory(){
if (!Directory.Exists(FILE_PATH)){
Directory.CreateDirectory(FILE_PATH);
}
}
// Reset Data If User Play 1st Time
private static void CheckFilesPreviousData(){
// Checking File is not Null
UserData tempObj = LoadUnLockLevelData();
if(tempObj == null){
const int FIRSTLEVEL = 1;
SaveUnLockedLevelData(FIRSTLEVEL);
Debug.Log("Donee");
}
}
#endregion
}
I have an empty GameObject on my Canvas used to display an ad menu, which I have attached to a separate script (not on the menu itself) in a public variable through the inspector.
I am setting it inactive in a script using adMenu.SetActive(false), which works on the first playthrough of my game. However, when I restart the scene through a button in my scene, the menu loses its reference to the same GameObject in the inspector, and I receive this error:
MissingReferenceException: The object of type 'GameObject' has been destroyed but you are still trying to access it.
This has never happened to me with other GameObjects initialized in similar ways after a scene reload.
Additional details:
GameObject.Find() can retrieve the GameObject using its name from within the same script
DontDestroyOnLoad() is not used anywhere on the script or on the GameObject it's attached to
Code:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Advertisements;
using MEC;
public class AdManager : MonoBehaviour, IUnityAdsListener
{
internal static AdManager instance;
private static bool isInitialized = false;
public GameObject adMenu;
private string placement = "rewardedVideo";
void Start()
{
instance = this;
if (!isInitialized)
{
isInitialized = true;
Advertisement.AddListener(this);
Advertisement.Initialize(Constants.appleGameId, true);
}
}
IEnumerator<float> ShowAd()
{
if (!Advertisement.IsReady())
{
yield return Timing.WaitForOneFrame;
}
Advertisement.Show(placement);
}
public void CloseAdMenu()
{
Debug.Log("Is adMenu null: " + (adMenu == null)); // Returns false on first playthrough only
adMenu.SetActive(false);
}
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
if (showResult == ShowResult.Finished)
{
CloseAdMenu();
}
}
public void OnUnityAdsReady(string placementId)
{
// throw new System.NotImplementedException();
}
public void OnUnityAdsDidError(string message)
{
// throw new System.NotImplementedException();
}
public void OnUnityAdsDidStart(string placementId)
{
// throw new System.NotImplementedException();
}
}
What happens has nothing to do with your menu object nor the static Instance.
The issue is the callback of
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
since you registered the instance via
Advertisement.AddListener(this);
but this instance will be Destroyer after the scene was changed.
As shown in the examples you should do
private void OnDestroy()
{
Advertisement.RemoveListener(this);
}
On your restart method, you should re-activate the button with adMenu.SetActive(true), if not, when you call the scene again, adMenu GameObject is disabled, so you can't access the GameObject.
Maybe you can add a method in your AdManager like:
public void OpenAdMenu()
{
adMenu.SetActive(true);
}
and call it on AdManager.Start()
I'm confused about finding reference GameObject but different Scene and set the onclick when difference scene, so I have GameManager who manage all but available only on the Main menu. So I decide to make Dontdestroyonload, the issue start at this, so when I play to the MainGame Scene, the field of GameManager at inspector will find, but I can't drag n drop different scene, right? That confuses me.
And if the GameManager at the MainMenu scene, the question is how to drag n drop at the onClick event, like I want pause button active or something else in the game.
]3
I tried with onLloadscene(scene s, Mode mode), but nothing happens, and here the scrip for the GameManager. :
public static GameManager gameManager;
[Header("Main Menu panels")]
public GameObject startPanel;
public GameObject settingPanel;
public GameObject levelPanel;
[Header("InGame Panels")]
#region Panel
public GameObject pausePanel;
public GameObject ObjectivePanel;
public GameObject shopPanel;
private int click = 0;
[Header("Int Tweaks")]
public int indexLevel;
public int onlevel;
public bool isPaused;
_levelSelect LevelSelect;
public static GameManager Instance { set; get; }
public int levelindexPlayerPrefs;
private void Awake()
{
if (gameManager != null)
{
Instance = this;
Destroy(gameObject);
}
else
{
DontDestroyOnLoad(gameObject);
}
}
void Start()
{
LevelSelect = FindObjectOfType<_levelSelect>();
OnStart();
onlevel = int.Parse(LevelSelect.levelIndex) + 1;
indexLevel = int.Parse(LevelSelect.levelIndex);
getPlayerData();
}
// Update is called once per frame
void Update()
{
ExitApp();
}
public void OnStart()
{
startPanel.SetActive(true);
settingPanel.SetActive(false);
levelPanel.SetActive(false);
}
#region Buttons
public void startbutton()
{
levelPanel.SetActive(true);
startPanel.SetActive(false);
settingPanel.SetActive(false);
}
public void backButtonMainMenu()
{
levelPanel.SetActive(false);
startPanel.SetActive(true);
settingPanel.SetActive(false);
}
public void settingbutton()
{
levelPanel.SetActive(false);
startPanel.SetActive(false);
settingPanel.SetActive(true);
}
public void PauseButton()
{
Time.timeScale = 0f;
pausePanel.SetActive(true);
ObjectivePanel.SetActive(false);
}
public void Resume()
{
Time.timeScale = 1f;
}
#endregion
public void ExitApp()
{
if (Input.GetKey(KeyCode.Escape))
{
click++;
StartCoroutine(ClickTime());
if (click>1)
{
print("Exit Game");
Application.Quit();
}
}
}
IEnumerator ClickTime()
{
yield return new WaitForSeconds(0.5f);
click = 0;
}
public void getPlayerData()
{
levelindexPlayerPrefs = PlayerPrefs.GetInt("LevelIndex", 0);
}
public void updateLevel(int Index)
{
if (levelindexPlayerPrefs < Index)
{
PlayerPrefs.SetInt("LevelIndex", Index);
levelindexPlayerPrefs = PlayerPrefs.GetInt("LevelIndex");
}
}
#region onloadedScenePickRefferences
private void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
pausePanel = GameObject.FindGameObjectWithTag("PausePanel");
ObjectivePanel = GameObject.FindGameObjectWithTag("ObjectivePanel");
}
#endregion
//public IEnumerator EndChapter()
//{
// updateLevel(indexLevel + 1);
// getPlayerData();
//}
Here is what I would probably do:
Have a static class for storing and sharing all your references. It doesn't have to be in any scene but simply "lives" in the assets:
public static class GlobalReferences
{
// as example just for one reference but you can implement the rest equally yourself
// here this class actually stores the reference
private static GameObject startPanel;
// A public property in order to add some logic
// other classes will always access and set the value through this property
public static GameObject StartPanel
{
get
{
// if the reference exists return it right away
if(startPanel) return startPanel;
// as a fallback try to find it
startPanel = GameObject.FindGameObjectWithTag("StartPanel");
// ofcourse it might still fail when you simply try to access it
// in a moment it doesn't exist yet
return startPanel;
}
set
{
startPanel = value;
// invoke an event to tell all listeners that the startPanel
// was just assigned
OnStartPanelReady?.Invoke();
}
}
// An event you will invoke after assigning a value making sure that
// other scripts only access this value after it has been set
// you can even directly pass the reference in
public static event Action<GameObject> OnStartPanelReady;
}
So now in your component(s) that is(are) in the new loaded scene you assign the value as early as possible (Awake). Here you can already store it via the Inspector since it is a scene reference:
public class ExampleSetter : MonoBehaviour
{
// already reference it via the Inspector
[SerializeField] private GameObject startPanel;
private void Awake()
{
// as a fallback
if(!startPanel) startPanel = GameObject.FindObjectWithTag("startPanel");
// assign it to the global class
GlobalReferences.StartPanel = startPanel;
}
}
And in other scenes that where already loaded before you add a listener so they do their stuff as soon as the other scene is ready:
public class ExampleConsumer : MonoBehaviour
{
[Header("Debug")]
[SerializeField] private GameObject startPanel;
private void Awake()
{
// Try to get the reference
startPanel = GlobalReferences.StartPanel;
// if this failed then wait until it is ready
if(!startPanel)
{
// it is save to remove callbacks even if not added yet
// makes sure a listener is always only added once
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
GlobalReferences.OnStartPanelReady += OnStartPanelReady;
}
// otherwise already do what you want
else
{
OnStartPanelReady(startPanel);
}
}
private void OnDestroy()
{
// always make sure to clean up callbacks when not needed anymore!
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
}
private void OnStartPanelReady(GameObject newStartPanel)
{
startPanel = newStartPanel;
// always make sure to clean up callbacks when not needed anymore!
GlobalReferences.OnStartPanelReady -= OnStartPanelReady;
// NOTE: It is possible that at this point it is null anyway if another
// class has set this actively to null ;)
if(startPanel)
{
// Now do something with the startPanel
}
}
}
The other way round when you need a reference in the new loaded Scene form the main scene ... it should already be set since the mainscene was loaded first and has already assigned its according references.
Now you can either go for this static class or simply implement the same logic for each reference that needs to be shared directly in an according component where you reference them via drag&drop .. it makes no difference since anyway you will use static fields and events that are not bound to any instance but the type(s) itself.
I have void Start() with string snapshotJson declared inside of it, and I have private void LoadGameData() that needs to call the value of snapshotJson. Declaring snapshotJson public doesn't work, I assume because of void. From what I read I should be using getters and setters, but I have no idea how they work and every guide I've read explaining it makes it seem very simple, but they explain it so simply I don't understand how exactly I'm supposed to use it, or how I can call the value after using the get/set functions.
Could anyone explain how I can get the variable from one class to another? In my code, LoadGameData isn't able to call the value of snapshotJson, I'm not sure what I'm missing.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using Firebase;
using Firebase.Unity.Editor;
using Firebase.Database;
using System;
public class DataController : MonoBehaviour
{
private RoundData[] allRoundData;
private PlayerProgress playerProgress;
[Serializable]
public class FirebaseStart : MonoBehaviour
{
public string snapshotJson { get; set; }
void Start()
{
// Set up the Editor before calling into the realtime database.
FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://FIREBASEDATABASE");
// Get the root reference location of the database.
DatabaseReference reference =
FirebaseDatabase.DefaultInstance.RootReference;
FirebaseDatabase.DefaultInstance
.GetReference("allRoundData")
.GetValueAsync().ContinueWith(task => {
if (task.IsFaulted)
{
// Handle the error...
}
else if (task.IsCompleted)
{
// DataSnapshot snapshot = task.Result;
snapshotJson = JsonUtility.ToJson(task.Result);
}
});
}
}
// Use this for initialization
void Start ()
{
DontDestroyOnLoad(gameObject);
LoadGameData();
LoadPlayerProgress();
SceneManager.LoadScene("MenuScreen");
}
public RoundData GetCurrentRoundData()
{
return allRoundData [0];
}
public void SubmitNewPlayerScore(int newScore)
{
if (newScore > playerProgress.highestScore)
{
playerProgress.highestScore = newScore;
SavePlayerProgress();
}
}
public int GetHighestPlayerScore()
{
return playerProgress.highestScore;
}
// Update is called once per frame
void Update () {
}
private void LoadPlayerProgress()
{
playerProgress = new PlayerProgress();
if (PlayerPrefs.HasKey("highestScore"))
{
playerProgress.highestScore = PlayerPrefs.GetInt("highestScore");
}
}
private void SavePlayerProgress()
{
PlayerPrefs.SetInt("highestScore", playerProgress.highestScore);
}
public void LoadGameData()
{
GameData loadedData = JsonUtility.FromJson<GameData>(snapshotJson);
Console.WriteLine(snapshotJson);
allRoundData = loadedData.allRoundData;
}
The LoadGameData() method cannot access it from the Main() method because it is local to that function scope. However, you can pass the value from the Main() method to the LoadGameData() using the code below:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
private static void LoadGameData(String input) {
// Do something inside your input here.
}
public static void Main() {
Start();
}
public static void Start()
{
string snapshotJson = "Sample data";
// Same Class Call
LoadGameData(snapshotJson);
// Other Class Call
var otherClassInstance = new TestClass();
otherClassInstance.LoadGameData(snapshotJson);
}
}
public class TestClass {
public void LoadGameData(String input) {
// Do something inside your input here.
}
}
Assuming you refer to methods instead of classes (or rather: sharing data between objects), this is what you could do. Here's an example of a dedicated class for your Game objects, with SnaphopJson being a public property that can be accessed and changed from any other object. Changing the setter to private would ensure only it can only be read from anything but objects of this class.
public class Game
{
public string SnapshotJson { get; set; }
private void LoadGameData()
{
// load the json, e.g. by deserialization
SnapshotJson = "{}";
}
public void Start()
{
// access the content of your snapshot
var s = SnapshotJson;
}
}
If the variable snapshotJson is declared inside the body of the Start method, it will only be accessible within that method. If you want the variable to be accessible in other methods of your class, you may want to declare it as a member variable. This is how it looks like. You would need to declare it as a public property only if you need to access the value of snapshotJson outside of your class instance.
public class MyClass
{
string snapshotJson;
private void Start()
{
// Assign value to snapshotJson here
snapshotJson = "foo";
}
private void LoadGameData
{
// Use value of snapshotJson here
string s = snapshotJson;
}
}