如果二进制文件已损坏,则重置进度

时间:2017-10-30 22:09:14

标签: c# unity3d

我在Unity游戏中使用二进制格式化程序来存储播放器的进度以跟踪他解锁的级别。使用此代码一切正常:

public static void Save()
{
    LevelManager levelManager = GameObject.Find ("GameManager").GetComponent<LevelManager> ();
    BinaryFormatter bf = new BinaryFormatter();
    FileStream file = File.Create (Application.persistentDataPath + "/savedProgress.1912");
    bf.Serialize(file, levelManager.levelReached);
    file.Close();
}

public static void Load() 
{
    LevelManager levelManager = GameObject.Find ("GameManager").GetComponent<LevelManager> ();
    if(File.Exists(Application.persistentDataPath + "/savedProgress.1912")) 
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Open(Application.persistentDataPath + "/savedProgress.1912", FileMode.Open);
        levelManager.levelReached = (int)bf.Deserialize(file);
        file.Close();
    }
}

它只是保存和int调用levelReached。保存进度后,将在您的计算机上添加一个新文件,在这种情况下&#34; savedProgress.1912&#34;。

如果我将文件编辑为文本,它看起来像这样:

https://i.gyazo.com/e604f83666f14424b6d45d15b16afacc.png

每当我替换或删除此文件中的内容时,它都会损坏并在Unity中给我以下错误:

System.Runtime.Remoting.Messaging.Header[]& headers) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:104)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:179)
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:136)
SaveLoadProgress.Load () (at Assets/Scripts/SaveLoadProgress.cs:25)
LevelManager.Start () (at Assets/Scripts/LevelManager.cs:16)

这个问题是,当我这样做时,我会解锁所有关卡。在播放之前,他们将回到他们在编辑器中的状态。我知道我可以将它们锁定为标准状态,但有没有办法不以另一种方式让它发生?

编辑:当我写这篇文章时,我意识到我刚刚说过的内容,只需按标准锁定所有级别,问题就解决了。虽然知道它仍然很好。

编辑:我知道使用this帖子中的代码。

这就是我目前正在使用的内容:

DataSaver.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Text;
using System;


public class DataSaver
{
    //Save Data
    public static void saveData<T>(T dataToSave, string dataFileName)
    {
        string tempPath = Path.Combine(Application.persistentDataPath, "data");
        tempPath = Path.Combine(tempPath, dataFileName + ".txt");

        //Convert To Json then to bytes
        string jsonData = JsonUtility.ToJson(dataToSave, true);
        byte[] jsonByte = Encoding.ASCII.GetBytes(jsonData);

        //Create Directory if it does not exist
        if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
        {
            Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
        }
        //Debug.Log(path);

        try
        {
            File.WriteAllBytes(tempPath, jsonByte);
            Debug.Log("Saved Data to: " + tempPath.Replace("/", "\\"));
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To PlayerInfo Data to: " + tempPath.Replace("/", "\\"));
            Debug.LogWarning("Error: " + e.Message);
        }
    }

    //Load Data
    public static T loadData<T>(string dataFileName)
    {
        string tempPath = Path.Combine(Application.persistentDataPath, "data");
        tempPath = Path.Combine(tempPath, dataFileName + ".txt");

        //Exit if Directory or File does not exist
        if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
        {
            Debug.LogWarning("Directory does not exist");
            return default(T);
        }

        if (!File.Exists(tempPath))
        {
            Debug.Log("File does not exist");
            return default(T);
        }

        //Load saved Json
        byte[] jsonByte = null;
        try
        {
            jsonByte = File.ReadAllBytes(tempPath);
            Debug.Log("Loaded Data from: " + tempPath.Replace("/", "\\"));
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To Load Data from: " + tempPath.Replace("/", "\\"));
            Debug.LogWarning("Error: " + e.Message);
        }

        //Convert to json string
        string jsonData = Encoding.ASCII.GetString(jsonByte);

        //Convert to Object
        object resultValue = JsonUtility.FromJson<T>(jsonData);
        return (T)Convert.ChangeType(resultValue, typeof(T));
    }

    public static bool deleteData(string dataFileName)
    {
        bool success = false;

        //Load Data
        string tempPath = Path.Combine(Application.persistentDataPath, "data");
        tempPath = Path.Combine(tempPath, dataFileName + ".txt");

        //Exit if Directory or File does not exist
        if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
        {
            Debug.LogWarning("Directory does not exist");
            return false;
        }

        if (!File.Exists(tempPath))
        {
            Debug.Log("File does not exist");
            return false;
        }

        try
        {
            File.Delete(tempPath);
            Debug.Log("Data deleted from: " + tempPath.Replace("/", "\\"));
            success = true;
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To Delete Data: " + e.Message);
        }

        return success;
    }
}

LevelManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Linq;
using UnityEngine.UI;

[System.Serializable]
public class LevelManager : MonoBehaviour {

    public GameObject[] levelButtons; 
    public int levelReached = 1;

    void Start()
    {
        //SaveLoadProgress.Load ();
        LevelManager loadedData = DataSaver.loadData<LevelManager>("Progress");
        if (loadedData == null)
        {
            return;
        }

        levelButtons = GameObject.FindGameObjectsWithTag ("Level").OrderBy (go => go.name).ToArray ();
        for (int i = 0; i < levelButtons.Length; i++) 
        {
            if (i + 1 > loadedData.levelReached) 
            {
                Color greyed = levelButtons [i].GetComponent<Image> ().color;
                greyed.a = 0.5f;
                levelButtons [i].GetComponent<Image> ().color = greyed;
            }
            if (i < loadedData.levelReached) 
            {
                Color normal = levelButtons [i].GetComponent<Image> ().color;
                normal.a = 1f;
                levelButtons [i].GetComponent<Image> ().color = normal;
            }
        }
    }

}

GameController.cs

if(--LEVELCOMPLETED--)
{
    LevelManager saveData = new LevelManager();
    saveData.levelReached = SceneManager.GetActiveScene ().buildIndex + 1;
    DataSaver.saveData(saveData, "Progress");
}

当我使用这些代码时,调试日志显示:Saved data to...loaded data from..但在loaded data from..之后,它会给我这个错误:

ArgumentException: Cannot deserialize JSON to new instances of type 'LevelManager.'
UnityEngine.JsonUtility.FromJson[LevelManager] (System.String json) (at C:/buildslave/unity/build/artifacts/generated/common/modules/JSONSerialize/JsonUtilityBindings.gen.cs:25)
DataSaver.loadData[LevelManager] (System.String dataFileName) (at Assets/Scripts/DataSaver.cs:77)
LevelManager.Start () (at Assets/Scripts/LevelManager.cs:17)

文件&#34; Progress.txt&#34;确实很激动。它看起来像这样:

{
    "levelButtons": [],
    "levelReached": 2
}

当我为Android或Apple发布时,modders是否能够看到此文件?如果我不想让人们作弊,我是否需要加密?我该怎么做?

0 个答案:

没有答案