- Home /
Persistent data, Save file doesn't come out as hoped
I have recently started with Unity. Currently I'm stuck when it comes to data persistence. While I can create a file, however it doesn't contain the serialized variable. I've already read and seen various tutorials. Unfortunately, I still do not get ahead. I would be very grateful if someone could help me.
This is my SaveLoad.cs I could use without editing much:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public static class SaveLoad {
public static List<Game> savedGames = new List<Game>();
public static void Save() {
savedGames.Add(Game.current);
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd");
bf.Serialize(file, SaveLoad.savedGames);
file.Close();
}
public static void Load() {
if(File.Exists(Application.persistentDataPath + "/savedGames.gd")) {
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/savedGames.gd", FileMode.Open);
SaveLoad.savedGames = (List<Game>)bf.Deserialize(file);
file.Close();
}
}
}
Here is my game.cs with the (I hope) serialized variable I try to save:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Game {
public static Game current;
public Click CurrentEuros { get; set; }
public Game () {
//CurrentEuros = 1;
CurrentEuros = new Click();
}
}
The outcome is alway in the last line of the savedGames.gd "Game".
^ It should throw an "Type XYZ is not marked as serializable" error.
Try saving and loading a single instance of Game ins$$anonymous$$d of a list.
Yes:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Click : $$anonymous$$onoBehaviour {
public UnityEngine.UI.Text eurosPerClick;
public UnityEngine.UI.Text eurosEarned;
public float euros = 0.00f;
public int eurosperclick { get; set; }
public Click()
{
eurosperclick = 1;
}
void Update(){
eurosEarned.text = euros.ToString ("F0") + " Splinter";
eurosPerClick.text = eurosperclick + " Splinter/click";
}
public void Clicked(){
euros += eurosperclick;
}
}
Someone told me I can't use static void, but the fact, that the class "File" is already static, makes it impossible to change the others into unstatic.
Answer by spiceboy9994 · May 27, 2015 at 05:06 PM
As Far as I know, MonoBehavior based clases cannot be serialized within files. I had the same issue when I was trying to save to an xml. What I did is to create a wrapper class with the only properties that I wanted to serialized or save. So you could try doing something like this:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class ClickProperties {
public float euros;
public float eurosPerClick;
}
public class Click: MonoBehavior {
public UnityEngine.UI.Text eurosPerClick;
public UnityEngine.UI.Text eurosEarned;
public ClickProperties myProps;
public Click()
{
myProps.eurosPerClick = 1;
}
void Update(){
eurosEarned.text = myProps.euros.ToString ("F0") + " Splinter";
eurosPerClick.text = myProps.eurosPerClick+ " Splinter/click";
}
public void Clicked(){
myProps.euros += myProps.eurosPerClick;
}
}
An then change Game Class to include the props instead of the monobehavior class:
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Game {
public static Game current;
public ClickProperties CurrentEuros { get; set; }
public Game () {
//CurrentEuros = 1;
CurrentEuros = new ClickProperties();
}
}
That was really helpful! But I got another problem in EuroPerSec.cs:
using UnityEngine;
using System.Collections;
public class EuroPerSec : $$anonymous$$onoBehaviour {
public UnityEngine.UI.Text epsDisplay;
public Click click;
public Item$$anonymous$$anager[] items;
void Start(){
StartCoroutine (AutoTick ());
}
void Update(){
epsDisplay.text = GetEuroPerSec () + " Splinter/sec";
}
public float GetEuroPerSec(){
float tick = 0;
foreach (Item$$anonymous$$anager item in items) {
tick += item.count * item.tickValue;
}
return tick;
}
public void AutoEuroPerSec(){
ClickProperties.euros += GetEuroPerSec () / 10;
}
IEnumerator AutoTick(){
while(true){
AutoEuroPerSec();
yield return new WaitForSeconds(0.10f);
}
}
}
The error accures due to ClickProperties.euros in AutoEuroPerSec().
Unless you have declared the euros property within the ClickProperties class as static, you cannot reference the property using the type. Within the example I gave you, I just declared as public
[System.Serializable]
public class ClickProperties {
public float euros;
public float eurosPerClick;
}
That requires that you use the class instance to access any property, according to your class and my class it could be using your singleton class:
public void AutoEuroPerSec(){
Game.current.CurrentEuros.euros += GetEuroPerSec () / 10;
}
(Assu$$anonymous$$g that you used my classes definition). Or also using a new instance of the class and place it wherever your logic needs it. For example
public class EuroPerSec : $$anonymous$$onoBehaviour {
public UnityEngine.UI.Text epsDisplay;
public Click click;
public Item$$anonymous$$anager[] items;
void Start(){
StartCoroutine (AutoTick ());
click.CurrentEuros = new ClickProperties()
}
public void AutoEuroPerSec(){
click.CurrentEuros.euros += GetEuroPerSec () / 10;
}
}
This depends entirely on your game logic. If the answer helped you, I would really appreciate a thumbs up :D!
Regards
This worked as fine as any other answer you gave. But now this cs-file gets an error:
using UnityEngine;
using System.Collections;
public class Save : $$anonymous$$onoBehaviour {
public void SaveNow(){
SaveLoad.Save();
}
public void LoadNow(){
SaveLoad.Load();
}
}
The errors says: Assets/Scripts/SaveLoad/Save.cs(7,26): error CS0120: An object reference is required to access non-static member `SaveLoad.Save()'
Actually two errors, for SaveLoad.Save() and SaveLoad.Load()
That's weird, I did not change anything on the Save Class on the examples that I've provide. Are those methods still public static?, if this is the case and the problem is still present, I could suggest removing the static qualifiers arround the SaveLoad class. So it would be something like:
public class SaveLoad {
public List<Game> savedGames = new List<Game>();
public void Save() {
//your code
}
public void Load() {
//your code
}
}
}
And then:
using UnityEngine;
using System.Collections;
public class Save : $$anonymous$$onoBehaviour {
SaveLoad saveLoadBehavior;
public void Start() {
saveLoadBehavior = new SaveLoad();
}
public void SaveNow(){
saveLoadBehavior.Save();
}
public void LoadNow(){
saveLoadBehavior.Load();
}
}
The main payback is related to the class instance created on the start of this object, but if you use this along with a DontDestroyOnLoad GameObject, it still can behave as a single instance within your game. That is an entire new topic to discuss.
Your answer
Follow this Question
Related Questions
Best way to save data 1 Answer
[C#]Persistent Saving and Loading 1 Answer
Unity Not Loading 0 Answers
Lots of persistent data 2 Answers
problem with create game Android 2 Answers