保存游戏状态的最佳方法是什么?

Q:

I find the best way to save game data in Unity3D Game engine.
我找到了在 Unity3D 游戏引擎中保存游戏数据的最佳方法。
At first, I serialize objects using BinaryFormatter.
首先,我使用BinaryFormatter序列化对象。

But I heard this way has some issues and is not suitable for save.
但我听说这种方式有一些问题,不适合保存。
So, What is the best or recommended way for saving game state?
那么,保存游戏状态的最佳或推荐方法是什么?

In my case, save format must be byte array.
就我而言,保存格式必须是字节数组。

A:

But I heard this way has some issues and not suitable for save.
但我听说这种方式有一些问题并且不适合保存。

That’s right. On some devices, there are issues with BinaryFormatter. It gets worse when you update or change the class. Your old settings might be lost since the classes non longer match. Sometimes, you get an exception when reading the saved data due to this.
这是正确的。在某些设备上, BinaryFormatter存在问题。当您更新或更改课程时,情况会变得更糟。由于类不再匹配,您的旧设置可能会丢失。有时,您在读取保存的数据时会遇到异常。

Also, on iOS, you have to add Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes"); or you will have problems with BinaryFormatter.
另外,在 iOS 上,您必须添加 Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes"); 否则您将遇到BinaryFormatter问题。

The best way to save is with PlayerPrefs and Json. You can learn how to do that here.
最好的保存方法是使用PlayerPrefsJson 。您可以在此处了解如何执行此操作。

In my case, save format must be byte array
就我而言,保存格式必须是字节数组

In this case, you can convert it to json then convert the json string to byte array. You can then use File.WriteAllBytes and File.ReadAllBytes to save and read the byte array.
在这种情况下,您可以将其转换为 json,然后将 json string转换为byte数组。然后,您可以使用File.WriteAllBytesFile.ReadAllBytes保存和读取字节数组。

Here is a Generic class that can be used to save data. Almost the-same as this but it does not use PlayerPrefs. It uses file to save the json data.
这是一个可用于保存数据的通用类。与几乎相同,但它使用PlayerPrefs 。它使用文件来保存json数据。

DataSaver class:
DataSaver类:

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;
    }
}

USAGE:
用法

Example class to Save:
要保存的示例类

[Serializable]
public class PlayerInfo
{
    public List<int> ID = new List<int>();
    public List<int> Amounts = new List<int>();
    public int life = 0;
    public float highScore = 0;
}

Save Data:  保存数据:

PlayerInfo saveData = new PlayerInfo();
saveData.life = 99;
saveData.highScore = 40;

//Save data from PlayerInfo to a file named players
DataSaver.saveData(saveData, "players");

Load Data:  加载数据:

PlayerInfo loadedData = DataSaver.loadData<PlayerInfo>("players");
if (loadedData == null)
{
    return;
}

//Display loaded Data
Debug.Log("Life: " + loadedData.life);
Debug.Log("High Score: " + loadedData.highScore);

for (int i = 0; i < loadedData.ID.Count; i++)
{
    Debug.Log("ID: " + loadedData.ID[i]);
}
for (int i = 0; i < loadedData.Amounts.Count; i++)
{
    Debug.Log("Amounts: " + loadedData.Amounts[i]);
}

Delete Data:  删除数据:

DataSaver.deleteData("players");
912sy.com下载资源均来源于网络,仅供学习和参考使用,版权归原作者所有,勿作商业用途,请在下载后24小时之内自觉删除。
本站发布的内容若无意中侵犯到您的权益,请联系我们,本站将在一个工作日内删除。如遇到任何问题请联系客服QQ:2385367137
912sy » 保存游戏状态的最佳方法是什么?