- Home /
Save and Load Problem
I'm almost finished with my game. The only thing I have left to do is to securely save and load game states. I want to save a game through the pause menu, and load it back through the main menu, or the submenu titled Sweet Spot (sometimes after the user starts the game.). Here is my code so far.
SaveManager.cs:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class SaveManager : MonoBehaviour
{
public static string directory = "SaveLoad";
public static string fileName = "saveFile.sav";
public static string gameFolder = "2D Indy";
public static string saveDirectory = Application.persistentDataPath + "/" + gameFolder + "/" + directory;
public static string savePath = saveDirectory + "/" + fileName;
public static void Save(Player player)
{
if (!DirectoryExists())
Directory.CreateDirectory(saveDirectory);
using (BinaryWriter bw = new BinaryWriter(File.Open(Application.persistentDataPath + "/" + directory + "/" + fileName, FileMode.Create)))
{
PlayerData data = PlayerData.FromPlayer(player);
bw.Write(data.Health);
bw.Write(data.Lives);
bw.Write(data.Score);
if (data.Position == null)
{
bw.Write(0);
}
bw.Write(data.Position.Length);
foreach (var value in data.Position)
{
bw.Write(value);
}
bw.Close();
}
}
public static PlayerData Load()
{
try
{
using (BinaryReader br = new BinaryReader(File.Open(Application.persistentDataPath + "/" + directory + "/" + fileName, FileMode.Open)))
{
PlayerData data = new PlayerData();
data.Health = br.ReadInt32();
data.Lives = br.ReadInt32();
data.Score = br.ReadInt32();
int length = br.ReadInt32();
data.Position = new float[length];
for (int index = 0; index < length; index++)
{
data.Position[index] = br.ReadSingle();
}
br.Close();
return data;
}
}
catch
{
Debug.LogError("Save file not found in " + Application.persistentDataPath + "/" + directory + "/" + fileName);
return null;
}
}
private static bool SaveExists()
{
return File.Exists(GetFullPath());
}
private static bool DirectoryExists()
{
saveDirectory = Application.persistentDataPath + "/" + directory;
return Directory.Exists(saveDirectory);
}
private static string GetFullPath()
{
savePath = saveDirectory + "/" + fileName;
return savePath;
}
}
SweetSpot.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SweetSpot : MonoBehaviour
{
public Player player;
// Start is called before the first frame update
void Start()
{
player = FindObjectOfType<Player>();
}
public void Load()
{
player.Load();
Debug.Log("Your game has been loaded.");
}
}
PauseScreen.cs:
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class PauseScreen : MonoBehaviour
{
public GameObject PauseCanvas;
public static bool GameIsPaused;
public PlayerController ball;
public Player player;
void Start()
{
GameIsPaused = false;
ball = FindObjectOfType<PlayerController>();
player = FindObjectOfType<Player>();
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Cancel"))
{
if (GameIsPaused)
{
Resume();
}
else
{
Pause();
}
}
}
public void Resume()
{
Time.timeScale = 1;
GameIsPaused = false;
PauseCanvas.SetActive(false);
}
public void Pause()
{
Time.timeScale = 0;
GameIsPaused = true;
PauseCanvas.SetActive(true);
}
public void MainMenu()
{
Resume();
SceneManager.LoadScene("MainMenu");
}
public void StartScreen()
{
Resume();
SceneManager.LoadScene("Intro");
}
public void Save()
{
player.Save();
Debug.Log("Your game has been saved.");
}
}
I can successfully save a game state to a file, but I'm unable to load it back from the file, especially from a different scene. Can anyone help with this? Any assistance would be appreciated. And also, please don't provide me with unsecured strategies such as PlayerPrefs or Binary Serialization. Thanks.
Sincerely, burchland2
You state that you have a problem with loading your data. How about you describe the actual thing that does not work? why does it not work or where does it fail?
Other then that: Why not binary serialization? Writing savedata to a binary file (even just serializing the object) would by far not be the weakest link in the chain if someone wanted to cheat with your current approach. (Especially if you might not be using an obfuscator?)
especially if you do something like parse your safedata to a JSON, use string compression on it and then write it to a binary file. This way you cannot change a number in the binary file to load a better score. You'd have to rewrite the complete savefile.
I heard from many people, including another Unity Answers user, and Microsoft themselves, that using binary serialization was a dangerous, inadvisable way to save and load data. Also, I honestly don't know how to transfer the whole code from SaveManager.cs to JSON. I think that the best bet would be to use BinaryWriter and BinaryReader to save and load the game respectively.
Went to look it up and you can color me surprised. I did not know that binary serialization was an actual security issue and allowed remote code execution. I assumed that you were only refering to security in a sense that people can manipulate their save-data.
assu$$anonymous$$g that you want to stick with your method, let's put that aside then: You still did not answer the crucial point: what fails with your current method? Why does it not work? Is there an error? if yes what kind and where?
Answer by burchland2 · Sep 18, 2021 at 09:03 PM
Edit: Never mind. I finally figured it out. I had to place the buttons on the same scene, and delete both the "Sweet Spot" scene and class. That's all. Sorry I wasted everyone's time.
Sincerely, burchland2