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

Bha*_*kar 2 c# unity-game-engine

我试图在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();
}
Run Code Online (Sandbox Code Playgroud)

这是我用来加载的代码:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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;
    }
} 
Run Code Online (Sandbox Code Playgroud)

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

我一直试图找出问题的真正原因,但整个问题对我来说根本没有意义.它总是将存储在playerData中任何变量中的任何大于400的数字更改为319.

Mat*_*nes 7

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

但是,您使用的是ASCII编码和文件ASCII.GetString规定:

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

Unicode的问号具有的价值0x3F-你原来的字节0x01,并0x90真正得到保存0x010x3F.

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

这是319.

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

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

研究保持对象的其他方法.