Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 保存游戏状态的最佳方法是什么?_C#_Unity3d_Savestate - Fatal编程技术网

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

C# 保存游戏状态的最佳方法是什么?,c#,unity3d,savestate,C#,Unity3d,Savestate,我找到了在Unity3D游戏引擎中保存游戏数据的最佳方法。 首先,我使用BinaryFormatter序列化对象 但我听说这种方式有一些问题,不适合保存。 那么,保存游戏状态的最佳或推荐方法是什么 在我的例子中,保存格式必须是字节数组 但我听说这种方式有一些问题,不适合保存 对。在某些设备上,BinaryFormatter存在问题。更新或更改类时,情况会变得更糟。由于类不再匹配,您的旧设置可能会丢失。有时,您在读取保存的数据时会因此发生异常 此外,在iOS上,您必须添加Environment.S

我找到了在Unity3D游戏引擎中保存游戏数据的最佳方法。
首先,我使用
BinaryFormatter
序列化对象

但我听说这种方式有一些问题,不适合保存。
那么,保存游戏状态的最佳或推荐方法是什么

在我的例子中,保存格式必须是字节数组

但我听说这种方式有一些问题,不适合保存

对。在某些设备上,
BinaryFormatter
存在问题。更新或更改类时,情况会变得更糟。由于类不再匹配,您的旧设置可能会丢失。有时,您在读取保存的数据时会因此发生异常

此外,在iOS上,您必须添加
Environment.SetEnvironmentVariable(“MONO_REFLECTION_SERIALIZER”,“yes”)
否则您将在使用
BinaryFormatter
时遇到问题

保存的最佳方法是使用
PlayerPrefs
Json
。你可以学习如何做到这一点

在我的例子中,保存格式必须是字节数组

在本例中,您可以将其转换为json,然后将json
字符串
转换为
字节
数组。然后可以使用
File.writealBytes
File.ReadAllBytes
保存和读取字节数组

下面是一个可用于保存数据的泛型类。几乎与相同,但它不使用
PlayerPrefs
。它使用文件来保存json数据

DataSaver
class:

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;
    }
}
加载数据:


我知道这篇文章很旧,但如果其他用户在搜索保存策略时也发现了它,请记住:

PlayerPrefs不用于存储游戏状态。它被显式命名为“PlayerPrefs”,以指示其用途:存储播放器首选项。它本质上是纯文本。它可以很容易地被任何玩家定位、打开和编辑。这可能不是所有开发人员都关心的问题,但对于许多具有竞争力的游戏来说,这很重要

使用PlayerPrefs进行选项菜单设置,如音量滑块和图形设置:播放器可以随意设置和更改这些设置


使用I/O和序列化保存游戏数据,或将其作为Json发送到服务器。这些方法比PlayerPrefs更安全,即使您在保存数据之前对数据进行了加密。

为什么您的格式必须是字节数组?为什么不保存到PlayerPrefs?使用序列化有什么问题吗?谢谢!因为我们的项目需要mono2x设置,所以我们没有通过该环境设置。我会尽量告诉你有用性和你的评论!嗨,我用了你的数据保存器,但它似乎不能保存字典?我查了本地文件。每个变量及其值都会保存,但不会保存到我的字典中。我认为这可能是显示问题,但当我加载它时,dict变量仍然为空。@SeakyLone没错。它不保存
字典
。这是因为Unity的
JsonUtility
无法序列化字典。我建议您编写一个扩展,将字典扁平化为数组或列表,然后对其进行序列化/反序列化。如果您不能做到这一点,那么请使用为Unity制作的
Newtonsoft.Json
版本,而不是代码中的
JsonUtility
,您应该能够对
字典
进行序列化/反序列化。非常感谢!!!我想我需要下载回购协议,我想这怎么行得通。非常感谢。我意识到已经3年了,但不要使用PlayerRefs来存储游戏状态。使用常规文件IO。
[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");