Unity拯救的不是float
,而是double
!这确实是一个很黑客的技巧,但如果你仔细观察,你会发现你的DWORD (32bit)
确实包含一个64
位long
!(不知道为什么他们没有正确 Select QWORD
或直接在那里进行二进制)
正如针对浮点类型已经提到的那样,您不能简单地削减bytes
并期望值保持与处理long
- int
相同.
你可以简单地使用
// Have in mind that the key here is NOT the one you use in Unity but also contains a certain trailing hash string
public static float GetFloat(string key, float fallback = 0f)
{
using (RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(@"Software\Unity\UnityEditor\" + Application.companyName + "\\" + Application.productName))
{
var value = registryKey?.GetValue(key);
if (value is long longValue)
{
// Convert the 64-bit value to a double
var doubleValue = BitConverter.Int64BitsToDouble(longValue);
// then simply cast to cut its precision down
var floatValue = (float)doubleValue;
return floatValue;
}
}
return fallback;
}
供您验证
var input = 12345678901234567890.1234567890f;
PlayerPrefs.SetFloat("TestFloat", input);
var output = GetFloat("TestFloat_h1435782019");
Assert.AreApproximatelyEqual(input,output, "Value retrieved from registry does not match the value stored in PlayerPrefs.");
我刚刚也跌了this snippet个
如果我们可以信任它,哈希字符串基本上计算为
public class PlayerPrefsHash
{
// Returns the string property name Unity would generate for a player prefs registry key value
// e.g., "PlayerGold" -> "PlayerGold_hXXXXXXXXXXXXXX"
public static string Hash(string name)
{
uint hash = 5381;
foreach (char c in name)
hash = hash * 33 ^ c;
string key = name + "_h" + hash;
return key;
}
}
因此,您可以在我上面的方法中使用它,并且能够在Unity上使用与WPF端相同的键常数.
至少在我的快速测试中,它似乎是准确的
var key = PlayerPrefsHash.Hash("TestFloat");
Assert.AreEqual("TestFloat_h1435782019", key, "PlayerPrefsHash.Hash does not match PlayerPrefs generated hash.");