Bhaskar Bhaskar - 1 month ago 14
C# Question

When loading player data any number above around 400 gets cut down to exactly 319

I am trying to save and load basic player data in Unity, but whenever I load the game everything loads properly except anything with a value stored that is a greater than 400, gets reduced to 319. For example, if I have saved 200 coins, it will load 200 coins, but if I have 500 coins, it will load 319 coins.

This is the code I use to save:

public static void save() {
Debug.Log("Saving Player Data");

//Convert Player Data to String
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, playerData);
byte[] newData = ms.ToArray();
string newDataString = Encoding.ASCII.GetString(newData);

FileStream file = File.Create(Application.persistentDataPath + "/playerData.aaa");
bf.Serialize(file, newDataString);
file.Close();
}


And here is the code I use to load:

public static void load() {
playerData = new PlayerData();
if(File.Exists(Application.persistentDataPath + "/playerData.aaa")) {
try {
Debug.Log("Loading Player Data");

BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/playerData.aaa", FileMode.Open);
string dataString = bf.Deserialize(file).ToString();
file.Close();

//Convert String to Player Data
byte[] playerDataBytes = Encoding.ASCII.GetBytes(dataString);
MemoryStream ms = new MemoryStream();
ms.Write(playerDataBytes, 0, playerDataBytes.Length);
ms.Seek(0, SeekOrigin.Begin);
playerData = (PlayerData)bf.Deserialize(ms);
} catch(Exception) {
Debug.Log("Messed Up Player Log: Creating New");
File.Delete(Application.persistentDataPath + "/playerData.aaa");
save();
}
} else {
Debug.Log("Player Data does not exist. Creating new and saving it");
save();
}
}


playerData is the object that contains the playerData. It is serializable.

Here is the code for the playerData:

using System.IO;

[System.Serializable]
public class PlayerData{
public bool tutorialComplete = false;

public ArtStyle artPrefs = ArtStyle.ORIGINAL;

public int coins = 0;

public ShopItem brightTexturePack = new ShopItem("Bright", 5);
public ShopItem neonTexturePack = new ShopItem("Neon", 50);
public ShopItem paperTexturePack = new ShopItem("Paper", 500);

public ShopItem getShopItem(string itemName) {
switch(itemName) {
case "BRIGHT":
return brightTexturePack;
case "NEON":
return neonTexturePack;
case "PAPER":
return paperTexturePack;
}
return null;
}
}

[System.Serializable]
public class ShopItem {
public int price;
public string name;
public bool isBought = false;

public ShopItem(string name, int price) {
this.price = price;
this.name = name;
}
}


The only places I have seen the issue occur is in the variable coins and the price of the Neon Texture Pack, because they are the only variables that normally reach above 400.

I have been trying to figure out what the issue is for really long, but the whole problem just doesn't make sense to me at all. It always changes any number greater than 400 stored in any of the variables in the playerData to 319.

Answer

Your problem is BinaryFormatter bf = new BinaryFormatter(); combined with Encoding.ASCII.GetString(newData); you can't call GetString on arbitrary data you are getting from your serialize call, you will see lost data like you are getting.

Use the JsonUtility class built in to unity to turn your class in to a string instead of using BinaryFormatter + GetString