Unity编辑器拓展之三十一:获取PlayerPrefs所有键值对

博客迁移

个人博客站点,欢迎访问,www.jiingfengji.tech

本文地址

PlayerPrefs官方文档,请戳这里~~~

正文

关于PlayerPrefs使用细节就不介绍了,实际上,在开发中,已经没怎么使用PlayerPrefs了,这里只是单纯的介绍一下如何获取所有的键值对,毕竟Unity并没有提供直接的接口。

Unity编辑器拓展之三十一:获取PlayerPrefs所有键值对_第1张图片

只有DeleteAll接口,没有GetAll接口。

本篇文章的主要代码来源于PlayerPrefs Editor插件,插件自行下载。

数据存储

Unity编辑器拓展之三十一:获取PlayerPrefs所有键值对_第2张图片

官方文档中有介绍,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}");
		}
	}
}

Unity编辑器拓展之三十一:获取PlayerPrefs所有键值对_第3张图片

以上知识分享,如有错误,欢迎指出,共同学习,共同进步。如果有不懂,欢迎留言评论!

你可能感兴趣的:(Unity编辑器拓展,Unity)