private void CacheRecord(string key, object value) { // First of all check if this key already exists, if so replace it's value with the new value bool replaced = false; int entryCount = deserializedPlayerPrefs.Count; for (int i = 0; i < entryCount; i++) { // Found the key - it exists already if (deserializedPlayerPrefs[i].Key == key) { deserializedPlayerPrefs[i] = new PlayerPrefPair() { Key = key, Value = value }; // Update the cached pref with the new value replaced = true; // Mark the replacement so we no longer need to add it break; } } // Player pref doesn't already exist (and wasn't replaced) so add it as new if (!replaced) { deserializedPlayerPrefs.Add(new PlayerPrefPair() { Key = key, Value = value }); // Cache a player pref the user just created so it can be instantly display (mainly for OSX) } // Update the search if it's active UpdateSearch(); }
/// <summary> /// This returns an array of the stored PlayerPrefs from the file system (OSX) or registry (Windows), to allow /// us to to look up what's actually in the PlayerPrefs. This is used as a kind of lookup table. /// </summary> private PlayerPrefPair[] RetrieveSavedPrefs(string companyName, string productName) { if (Application.platform == RuntimePlatform.OSXEditor) { // From Unity docs: On Mac OS X PlayerPrefs are stored in ~/Library/Preferences folder, in a file named unity.[company name].[product name].plist, where company and product names are the names set up in Project Settings. The same .plist file is used for both Projects run in the Editor and standalone players. // Construct the plist filename from the project's settings string plistFilename = string.Format("unity.{0}.{1}.plist", companyName, productName); // Now construct the fully qualified path string playerPrefsPath = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Preferences"), plistFilename); // Parse the player prefs file if it exists if (File.Exists(playerPrefsPath)) { // Parse the plist then cast it to a Dictionary object plist = Plist.readPlist(playerPrefsPath); Dictionary <string, object> parsed = plist as Dictionary <string, object>; // Convert the dictionary data into an array of PlayerPrefPairs PlayerPrefPair[] tempPlayerPrefs = new PlayerPrefPair[parsed.Count]; int i = 0; foreach (KeyValuePair <string, object> pair in parsed) { if (pair.Value.GetType() == typeof(double)) { // Some float values may come back as double, so convert them back to floats tempPlayerPrefs[i] = new PlayerPrefPair() { Key = pair.Key, Value = (float)(double)pair.Value }; } else { tempPlayerPrefs[i] = new PlayerPrefPair() { Key = pair.Key, Value = pair.Value }; } i++; } // Return the results return(tempPlayerPrefs); } else { // No existing player prefs saved (which is valid), so just return an empty array return(new PlayerPrefPair[0]); } } else if (Application.platform == RuntimePlatform.WindowsEditor) { // From Unity docs: On Windows, PlayerPrefs are stored in the registry under HKCU\Software\[company name]\[product name] key, where company and product names are the names set up in Project Settings. #if UNITY_5_5_OR_NEWER // From Unity 5.5 editor player prefs moved to a specific location Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\\Unity\\UnityEditor\\" + companyName + "\\" + productName); #else Microsoft.Win32.RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\\" + companyName + "\\" + productName); #endif // Parse the registry if the specified registryKey exists if (registryKey != null) { // Get an array of what keys (registry value names) are stored string[] valueNames = registryKey.GetValueNames(); // Create the array of the right size to take the saved player prefs PlayerPrefPair[] tempPlayerPrefs = new PlayerPrefPair[valueNames.Length]; // Parse and convert the registry saved player prefs into our array int i = 0; foreach (string valueName in valueNames) { string key = valueName; // Remove the _h193410979 style suffix used on player pref keys in Windows registry int index = key.LastIndexOf("_"); key = key.Remove(index, key.Length - index); // Get the value from the registry object ambiguousValue = registryKey.GetValue(valueName); // Unfortunately floats will come back as an int (at least on 64 bit) because the float is stored as // 64 bit but marked as 32 bit - which confuses the GetValue() method greatly! if (ambiguousValue.GetType() == typeof(int)) { // If the player pref is not actually an int then it must be a float, this will evaluate to true // (impossible for it to be 0 and -1 at the same time) if (PlayerPrefs.GetInt(key, -1) == -1 && PlayerPrefs.GetInt(key, 0) == 0) { // Fetch the float value from PlayerPrefs in memory ambiguousValue = PlayerPrefs.GetFloat(key); } } else if (ambiguousValue.GetType() == typeof(byte[])) { // On Unity 5 a string may be stored as binary, so convert it back to a string ambiguousValue = System.Text.Encoding.Default.GetString((byte[])ambiguousValue); } // Assign the key and value into the respective record in our output array tempPlayerPrefs[i] = new PlayerPrefPair() { Key = key, Value = ambiguousValue }; i++; } // Return the results return(tempPlayerPrefs); } else { // No existing player prefs saved (which is valid), so just return an empty array return(new PlayerPrefPair[0]); } } else { throw new NotSupportedException("PlayerPrefsEditor doesn't support this Unity Editor platform"); } }
/// <summary> /// This returns an array of the stored PlayerPrefs from the file system (OSX) or registry (Windows), to allow /// us to to look up what's actually in the PlayerPrefs. This is used as a kind of lookup table. /// </summary> private IEnumerable <PlayerPrefPair> RetrieveSavedPrefs(string companyName, string productName) { switch (Application.platform) { case RuntimePlatform.OSXEditor: { string playerPrefsPath; if (_showEditorPrefs) { // From Unity Docs: On macOS, EditorPrefs are stored in ~/Library/Preferences/com.unity3d.UnityEditor.plist. string majorVersion = Application.unityVersion.Split('.')[0]; // Construct the fully qualified path playerPrefsPath = Path.Combine( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Preferences"), "com.unity3d.UnityEditor" + majorVersion + ".x.plist"); } else { // From Unity Docs: On Mac OS X PlayerPrefs are stored in ~/Library/Preferences folder, in a file named unity.[company name].[product name].plist, where company and product names are the names set up in Project Settings. The same .plist file is used for both Projects run in the Editor and standalone players. // Construct the plist filename from the project's settings string plistFilename = $"unity.{companyName}.{productName}.plist"; // Now construct the fully qualified path playerPrefsPath = Path.Combine( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Preferences"), plistFilename); } // Parse the PlayerPrefs file if it exists if (!File.Exists(playerPrefsPath)) { return(new PlayerPrefPair[0]); } // Parse the plist then cast it to a Dictionary object plist = Plist.readPlist(playerPrefsPath); Dictionary <string, object> parsed = plist as Dictionary <string, object>; // Convert the dictionary data into an array of PlayerPrefPairs List <PlayerPrefPair> tempPlayerPrefs = new List <PlayerPrefPair>(parsed.Count); foreach (KeyValuePair <string, object> pair in parsed) { switch (pair.Value) { case double value: { // Some float values may come back as double, so convert them back to floats tempPlayerPrefs.Add(new PlayerPrefPair { Key = pair.Key, Value = (float)value }); break; } case bool _: { // Unity PlayerPrefs API doesn't allow bools, so ignore them break; } default: { tempPlayerPrefs.Add(new PlayerPrefPair { Key = pair.Key, Value = pair.Value }); break; } } } // Return the results return(tempPlayerPrefs.ToArray()); } case RuntimePlatform.WindowsEditor: { Microsoft.Win32.RegistryKey registryKey; if (_showEditorPrefs) { string majorVersion = Application.unityVersion.Split('.')[0]; #if UNITY_5_5_OR_NEWER registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey( "Software\\Unity Technologies\\Unity Editor 5.x"); #else registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey( "Software\\Unity Technologies\\Unity Editor " + majorVersion + ".x"); #endif } else { // From Unity docs: On Windows, PlayerPrefs are stored in the registry under HKCU\Software\[company name]\[product name] key, // where company and product names are the names set up in Project Settings. #if UNITY_5_5_OR_NEWER // From Unity 5.5 editor PlayerPrefs moved to a specific location registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey( "Software\\Unity\\UnityEditor\\" + companyName + "\\" + productName); #else registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\\" + companyName + "\\" + productName); #endif } // Parse the registry if the specified registryKey exists if (registryKey == null) { return(new PlayerPrefPair[0]); } // Get an array of what keys (registry value names) are stored string[] valueNames = registryKey.GetValueNames(); // Create the array of the right size to take the saved PlayerPrefs PlayerPrefPair[] tempPlayerPrefs = new PlayerPrefPair[valueNames.Length]; // Parse and convert the registry saved PlayerPrefs into our array int i = 0; foreach (string valueName in valueNames) { string key = valueName; // Remove the _h193410979 style suffix used on PlayerPref keys in Windows registry int index = key.LastIndexOf("_", StringComparison.Ordinal); key = key.Remove(index, key.Length - index); // Get the value from the registry object ambiguousValue = registryKey.GetValue(valueName); // Unfortunately floats will come back as an int (at least on 64 bit) because the float is stored as // 64 bit but marked as 32 bit - which confuses the GetValue() method greatly! if (ambiguousValue is int) { // If the PlayerPref is not actually an int then it must be a float, this will evaluate to true // (impossible for it to be 0 and -1 at the same time) if (GetInt(key, -1) == -1 && GetInt(key, 0) == 0) { // Fetch the float value from PlayerPrefs in memory ambiguousValue = GetFloat(key); } else if (_showEditorPrefs && (GetBool(key, true) != true || GetBool(key, false) != false)) { // If it reports a non default value as a bool, it's a bool not a string ambiguousValue = GetBool(key); } } else if (ambiguousValue.GetType() == typeof(byte[])) { // On Unity 5 a string may be stored as binary, so convert it back to a string ambiguousValue = Encoding.GetString((byte[])ambiguousValue).TrimEnd('\0'); } // Assign the key and value into the respective record in our output array tempPlayerPrefs[i] = new PlayerPrefPair() { Key = key, Value = ambiguousValue }; i++; } // Return the results return(tempPlayerPrefs); } default: { throw new NotSupportedException("PlayerPrefsEditor doesn't support this Unity Editor platform"); } } }