Unity项目中替换float为Double后,如何用PlayerPrefs存储数据?
解决float精度不足转double后PlayerPrefs无法存储的问题
兄弟,我太懂你这种糟心的情况了!之前做挂机金币系统的时候,也踩过一模一样的坑——一开始用float存金币,数值涨到200万之后,每秒加的那点小金币完全没反应,后来才反应过来是float的精度限制在搞鬼:float只有6-7位有效数字,200万已经占满7位了,再叠加小增量会直接被舍掉,根本存不进去。换成double之后精度问题解决了,结果又卡到PlayerPrefs不支持存double的坎儿上,给你分享几个亲测好用的解决办法:
方法一:转成字符串存储(最简单直接)
PlayerPrefs支持存储字符串,我们可以把double转成字符串存进去,读取的时候再解析回来:
// 存储double类型的金币值 double playerGold = 2500000.5; PlayerPrefs.SetString("PlayerGold", playerGold.ToString()); PlayerPrefs.Save(); // 读取金币值,处理首次读取无数据的情况 if (PlayerPrefs.HasKey("PlayerGold")) { if (double.TryParse(PlayerPrefs.GetString("PlayerGold"), out double loadedGold)) { playerGold = loadedGold; } else { // 解析失败时设默认值 playerGold = 0; } } else { playerGold = 0; }
这个方法优点是代码简单易维护,缺点是如果数值特别大,字符串解析会有一点点性能开销,但对于金币系统这种场景完全可以忽略。
方法二:把double拆分为两个int存储(无字符串解析开销)
double是64位的,我们可以用BitConverter把它拆成两个32位的int,分别存在PlayerPrefs里,读取的时候再合并回去:
// 存储double值 double playerGold = 2500000.5; byte[] doubleBytes = BitConverter.GetBytes(playerGold); // 拆分高32位和低32位 PlayerPrefs.SetInt("Gold_High", BitConverter.ToInt32(doubleBytes, 0)); PlayerPrefs.SetInt("Gold_Low", BitConverter.ToInt32(doubleBytes, 4)); PlayerPrefs.Save(); // 读取并合并double值 if (PlayerPrefs.HasKey("Gold_High") && PlayerPrefs.HasKey("Gold_Low")) { byte[] loadedBytes = new byte[8]; BitConverter.GetBytes(PlayerPrefs.GetInt("Gold_High")).CopyTo(loadedBytes, 0); BitConverter.GetBytes(PlayerPrefs.GetInt("Gold_Low")).CopyTo(loadedBytes, 4); playerGold = BitConverter.ToDouble(loadedBytes, 0); } else { playerGold = 0; }
这个方法完全避开了字符串操作,性能更优,但代码稍微复杂一点,适合对性能有要求的场景。
额外提醒:为什么float会失效?
再给你补个知识点,避免以后踩同类坑:float的有效精度只有6-7位十进制数字,当你的金币数到2000000(7位)时,float已经无法精确表示比1更小的增量了——比如你加0.5,它会直接被舍入成0,所以看起来数值不再增长。而double有15-17位有效精度,足够支撑大数值加小增量的场景,这也是你换double的原因选对了!
内容的提问来源于stack exchange,提问作者Arthur Belkin
相关产品推荐
相关产品推荐

