个人博客站点,欢迎访问,www.jiingfengji.tech
本文地址
PlayerPrefs官方文档,请戳这里~~~
关于PlayerPrefs使用细节就不介绍了,实际上,在开发中,已经没怎么使用PlayerPrefs了,这里只是单纯的介绍一下如何获取所有的键值对,毕竟Unity并没有提供直接的接口。
只有DeleteAll接口,没有GetAll接口。
本篇文章的主要代码来源于PlayerPrefs Editor插件,插件自行下载。
官方文档中有介绍,MacOS下存储在~/Library/Preferences文件夹下的unity.[company name].[product name].plist文件中,而Window下\Software[company name][product name]注册表中,因此待会儿获取代码中,MacOS下需要解析到plist文件,而Window下则需要读取注册表。
定义一个结构体PlayerPrefPair对应keyvalue键值对。
using System;
[Serializable]
public struct PlayerPrefPair
{
public string Key { get; set; }
public object Value { get; set; }
}
获取键值对的主要代码:
using System;
using System.Collections.Generic;
using System.IO;
using Sabresaurus.PlayerPrefsExtensions;
using UnityEditor;
using UnityEngine;
public static class PlayerPrefsExtension
{
public static PlayerPrefPair[] GetAll()
{
return GetAll(PlayerSettings.companyName, PlayerSettings.productName);
}
public static PlayerPrefPair[] GetAll(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");
}
}
}
其中关于MacOS下解析plist文件呢,PlayerPrefsEditor插件里使用的一个开源库:https://github.com/animetrics/PlistCS
最后,编写一点测试代码:
using UnityEditor;
public class PlayerPrefsTool : Editor
{
[MenuItem("Tools/PrintAllPlayerPrefs")]
public static void LogAllPlayerPrefs()
{
PlayerPrefPair[] keyValues = PlayerPrefsExtension.GetAll();
for (int i = 0; i < keyValues.Length; i++)
{
UnityEngine.Debug.Log($"key={keyValues[i].Key} value={keyValues[i].Value}");
}
}
}
以上知识分享,如有错误,欢迎指出,共同学习,共同进步。如果有不懂,欢迎留言评论!