Каков наилучший способ сохранить состояние игры?

Я нахожу лучший способ сохранить данные игры в Unity3D Game engine.
Сначала я сериализую объекты с помощью BinaryFormatter.

но я слышал, что этот способ имеет некоторые проблемы и не подходит для сохранения.
Итак, каков наилучший или рекомендуемый способ сохранения состояния игры?

в моем случае формат сохранения должен быть массивом байтов.

1 ответов


но я слышал, что этот способ имеет некоторые проблемы и не подходит для сохранения.

это верно. На некоторых устройствах, есть проблемы с BinaryFormatter. Это становится хуже, когда вы обновляете или меняете класс. Ваши старые настройки могут быть потеряны, так как классы больше не совпадают. Иногда вы получаете исключение при чтении сохраненных данных из-за этого.

кроме того, на iOS, вы должны добавить Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes"); или у вас будут проблемы с BinaryFormatter.

лучшие способ сохранить с PlayerPrefs и Json. Вы можете узнать, как это сделать здесь.

в моем случае формат сохранения должен быть массивом байтов

в этом случае вы можете преобразовать его в json, а затем преобразовать json string to byte массив. Затем вы можете использовать File.WriteAllBytes и File.ReadAllBytes для сохранения и чтения массива байтов.

вот общий класс, который можно использовать для сохранения данных. Почти то же самое, что этой но это не использовать PlayerPrefs. Он использует файл для сохранения данных json.

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

использование:

пример класса для сохранения:

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

Сохранить Данные:

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

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

Загрузка Данных:

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

Удалить Данные:

DataSaver.deleteData("players");