web-dev-qa-db-ja.com

ゲームの状態を保存する最良の方法は何ですか?

Unity3Dゲームエンジンでゲームデータを保存する最良の方法を見つけました。
最初は、BinaryFormatterを使用してオブジェクトをシリアル化します。

しかし、この方法にはいくつかの問題があり、保存には適していないと聞きました。
では、ゲームの状態を保存するための最良または推奨される方法は何ですか?

私の場合、保存形式はバイト配列でなければなりません。

13
Sizzling

しかし、この方法にはいくつかの問題があり、保存には適していないと聞きました。

そのとおり。一部のデバイスでは、BinaryFormatterに問題があります。クラスを更新または変更すると、状況はさらに悪化します。クラスが一致しなくなったため、古い設定が失われる可能性があります。このため、保存されたデータを読み取るときに例外が発生することがあります。

また、iOSではEnvironment.SetEnvironmentVariable("MONO_REFLECTION_SERIALIZER", "yes");を追加する必要があります。そうしないと、BinaryFormatterで問題が発生します。

保存する最良の方法は、PlayerPrefsおよびJsonを使用することです。その方法を学ぶことができます ここ

私の場合、保存形式はバイト配列でなければなりません

この場合、それをjsonに変換してから、json stringbyte配列に変換できます。その後、File.WriteAllBytesおよびFile.ReadAllBytesは、バイト配列を保存して読み取ります。

データの保存に使用できるGenericクラスは次のとおりです。 this とほぼ同じですが、-notと同じですが、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");
32
Programmer