【问题标题】:Save Double with PlayerPrefs?使用 PlayerPrefs 保存双倍?
【发布时间】:2018-04-01 01:44:02
【问题描述】:

在我的一个项目中,我最初开始使用浮点数,但过了一会儿我意识到它的精度并不是我想要的。我有一个自动化系统,每秒增加 X 个硬币的价值,并且考虑到浮动数量很大(超过 200 万),它不再给它增加这么小的价值。

所以我的下一个调用是使用双精度而不是浮点数。在将所有内容从浮点数更改为双精度数后,我意识到我将值存储在 PlayerPrefs 中,我想我不能存储双精度数?所以现在我有点困惑。

如何从 PlayerPrefs 中提取现有的浮点信息并将该浮点值放入双精度值,然后将该双精度值保存在 PlayerPrefs 中?我有点困惑,所以我正在寻求帮助。

这是我的部分代码:

// old
// public float totalP;

// new    
public double totalP;

void OnEnable()
{

    if (!PlayerPrefs.HasKey ("game_totalP")) 
    {
        PlayerPrefs.SetFloat ("game_totalP", totalP);
    } 
    else 
    {
        totalP = PlayerPrefs.GetFloat ("game_totalP");
    }        
}

任何帮助将不胜感激!

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    您可以将double 编码为两个int 并存储和检索它们。

    存储:

    var storeBytes = BitConverter.GetBytes(totalP);
    var storeIntLow = BitConverter.ToInt32(storeBytes, 0);
    var storeIntHigh = BitConverter.ToInt32(storeBytes, 4);
    PlayerPrefs.SetInt("game_totalP_low", storeIntLow);
    PlayerPrefs.SetInt("game_totalP_high", storeIntHigh);
    

    检索:

    var retrieveBytes = new byte[8];
    Array.Copy(BitConverter.GetBytes(storeIntLow), retrieveBytes, 4);
    Array.Copy(BitConverter.GetBytes(storeIntHigh), 0, retrieveBytes, 4, 4);
    totalP = BitConverter.ToDouble(retrieveBytes, 0);
    

    【讨论】:

      【解决方案2】:

      您可以使用PlayerPrefs 节省双倍费用。相应的 PlayerPrefs 函数是 PlayerPrefs.SetString 而不是 PlayerPrefs.GetFloat

      要保存的双倍:

      public double totalP;
      

      保存

      转成字符串

      string totalPStr = totalP.ToString();
      

      另存为字符串

      PlayerPrefs.SetString("game_totalP", totalPStr)
      

      加载

      加载为字符串

      string tempPStr = PlayerPrefs.GetString("game_totalP");
      

      将字符串转换为双精度

      totalP = double.Parse(tempPStr, System.Globalization.CultureInfo.InvariantCulture);
      

      如果您在使用 totalP.ToString() 时遇到科学记数法问题,请将其更改为 totalP.ToString("F6")。最后,我认为你应该放弃PlayerPrefs 并使用序列化来保存你的数据。请参阅this 帖子了解更多信息。

      【讨论】:

      • 非常感谢您的澄清!我想我现在明白它是如何工作的了。下一个问题是,如何检索旧数据并将其替换为字符串?如,我曾经这样做: if (!SecurePlayerPrefs.HasKey ("game_totalP")) { SecurePlayerPrefs.SetFloat ("game_totalP", totalP); } else { totalP= SecurePlayerPrefs.GetFloat ("game_totalP");如果 playerPrefs 中没有任何字符串,我该怎么做,用现有的浮点值替换它?
      • 我假设我必须将浮点数转换为双精度(或字符串)?
      • 你有没有读过答案?我使用了PlayerPrefs.SetStringPlayerPrefs.GetString 而不是 PlayerPrefs.SetFloatSecurePlayerPrefs.GetFloat,但您的评论显示了一些不同的东西。不要为此使用SetFloatGetFloat。请再次阅读此答案。
      • 是的,我做到了?你当时没有理解我的第二个问题。我得到了你的初步答案,我很感激。我的意思是我在 SetFloat/GetFloat 中有我想在 GetString 中使用的现有数据,如果这有意义的话?就像,如果我使用当前代码,一切都会从零开始。我希望它检查 PlayerPrefs.Haskey 是否从字符串值的“game_totalP”值返回 false,并将其替换为现有的 float 值,但改为字符串。
      • 非常感谢!!很高兴我终于可以理解它的实际工作原理了。
      【解决方案3】:

      我不仅可以添加评论,还可以重写 jdphenix 为现有的 PlayerPrefsX 扩展创建的内容。大多数使用 playerprefs 的人只会使用它,所以在这里:

      public static double GetDouble(string key)
      {
          var retrieveBytes = new byte[8];
          Array.Copy(BitConverter.GetBytes(PlayerPrefs.GetInt(key+"_doubleLowBits")), retrieveBytes, 4);
          Array.Copy(BitConverter.GetBytes(PlayerPrefs.GetInt(key+"_doubleHighBits")), 0, retrieveBytes, 4, 4);
          return BitConverter.ToDouble(retrieveBytes, 0);
      }
      
      public static void SetDouble(string key, double defaultValue)
      {
          var storeBytes = BitConverter.GetBytes(defaultValue);
          var storeIntLow = BitConverter.ToInt32(storeBytes, 0);
          var storeIntHigh = BitConverter.ToInt32(storeBytes, 4);
          PlayerPrefs.SetInt(key+"_doubleLowBits", storeIntLow);
          PlayerPrefs.SetInt(key+"_doubleHighBits", storeIntHigh);
      }
      

      这是为其他从谷歌来到这里试图找到这个答案的人准备的......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多