当加载玩家数据时,任何高于400的数字都会被削减到319

本文关键字:数字 数据 玩家 加载 任何高 | 更新日期: 2023-09-27 18:12:54

我试图在Unity中保存和加载基本的玩家数据,但每当我加载游戏时,除了存储值大于400的内容外,所有内容都可以正常加载,并减少到319。例如,如果我存了200个硬币,它将加载200个硬币,但如果我存了500个硬币,它将加载319个硬币。

这是我用来保存的代码:
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();
}
下面是我用来加载的代码:
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是包含playerData的对象。它是可序列化的。

下面是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;
    }
} 

我唯一看到问题发生的地方是可变硬币和霓虹纹理包的价格,因为它们是唯一的变量,通常达到400以上。

我一直想弄清楚问题是什么,但整个问题对我来说根本没有意义。它总是将存储在playerData中的任何变量中的大于400的任何数字更改为319。

当加载玩家数据时,任何高于400的数字都会被削减到319

当您序列化您的对象时,int字段正在被序列化-值400(十六进制的0x0190)被序列化为两个字节:0x010x90

但是,您正在使用ASCII编码和ASCII.GetString状态的文档:

ASCIIEncoding不提供错误检测。任何大于十六进制0x7F的字节都被解码为Unicode问号("?")。

Unicode问号的值为0x3F - 0x010x90的原始字节实际上被保存为0x010x3F

猜猜十六进制数0x013F的十进制是多少?

319 .

由于您使用ASCII.GetString,任何高于383 (0x017F)的数字将始终被序列化为319。

实际上,我刚刚意识到,任何具有大于0x7F的低顺序字节值的数字都将使用您的序列化进行更改,因此尝试保存128个硬币将导致您的加载方法返回63个硬币的值。

你的问题是BinaryFormatter bf = new BinaryFormatter();Encoding.ASCII.GetString(newData);相结合,你不能在你从序列化调用中获得的任意数据上调用GetString,你会看到丢失的数据,就像你得到的一样。

使用unity内置的JsonUtility类将您的类转换为字符串,而不是使用BinaryFormatter + GetString