web-dev-qa-db-fra.com

Quelle est la meilleure façon de sauvegarder l'état du jeu?

Je trouve le meilleur moyen de sauvegarder les données de jeu dans le moteur de jeu Unity3D.
Au début, je sérialise des objets en utilisant BinaryFormatter.

Mais j'ai entendu que cette façon de faire posait quelques problèmes et ne pouvait pas être sauvegardée.
Alors, quel est le meilleur moyen ou recommandé pour sauvegarder l'état du jeu?

Dans mon cas, le format de sauvegarde doit être un tableau d'octets.

13
Sizzling

Mais j'ai entendu que cette façon avait quelques problèmes et ne pouvait pas être sauvegardée.

C'est vrai. Sur certains appareils, il y a des problèmes avec BinaryFormatter. Cela empire lorsque vous mettez à jour ou changez la classe. Vos anciens paramètres peuvent être perdus car les classes ne correspondent plus. Parfois, vous obtenez une exception lors de la lecture des données enregistrées à cause de cela.

De plus, sur iOS, vous devez ajouter Environment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes"); ou vous aurez des problèmes avec BinaryFormatter.

La meilleure façon d'économiser est avec PlayerPrefs et Json. Vous pouvez apprendre à le faire ici .

Dans mon cas, le format de sauvegarde doit être un tableau d'octets

Dans ce cas, vous pouvez le convertir en json puis convertir le tableau json string en byte. Vous pouvez ensuite utiliser File.WriteAllBytes et File.ReadAllBytes pour enregistrer et lire le tableau d'octets.

Voici une classe générique qui peut être utilisée pour enregistrer des données. Presque identique à this mais il n'utilise pas PlayerPrefs. Il utilise un fichier pour enregistrer les données json.

DataSaver classe:

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

[~ # ~] utilisation [~ # ~] :

Exemple de classe à enregistrer:

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

Enregistrer les données:

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

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

Charger les données:

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

Supprimer les données:

DataSaver.deleteData("players");
32
Programmer