Unity PlayerPrefs生成同名不同注册表项的原因咨询
从你的描述来看,核心问题是看似相同的变量名,实际因为隐藏字符的差异,被PlayerPrefs识别为不同的键,导致注册表生成重复项。结合你提到的「文本文件来源的空值格式(如1-1)会出问题,手动编写的不会」,最可能的原因是文本文件的换行符/不可见空白字符差异,具体分析和解决步骤如下:
最可能的原因:文本文件的隐藏换行符
你手动编写的变量名用的是"\n"(换行符),但Windows系统下的文本文件默认换行符是"\r\n"(回车+换行),部分编辑器或系统也可能用"\r"作为换行符。当你读取文本文件的每行时,可能不小心把行尾的"\r"(ASCII码13)包含进了变量名里——比如从文本文件读来的"1-1"实际是"1-1\r",而你手动写的是"1-1",两者肉眼看起来一样,但PlayerPrefs会把它们当作完全不同的键,自然会生成两个不同的注册表项。
另外,也有可能是文本文件里的行包含了其他不可见字符(比如空格、制表符),导致变量名看似相同实际不同。
排查验证方法
你可以通过打印变量名的长度和每个字符的ASCII码,快速确认是否存在隐藏字符:
// 假设fileVar是从文本文件读取的变量名,manualVar是手动编写的 string fileVar = "从文本文件获取的1-1"; string manualVar = "1-1"; // 打印长度对比 Debug.Log($"文本文件变量名长度:{fileVar.Length},手动变量名长度:{manualVar.Length}"); // 逐个字符打印ASCII码 foreach (char c in fileVar) { Debug.Log($"文本字符:'{c}',ASCII码:{(int)c}"); } foreach (char c in manualVar) { Debug.Log($"手动字符:'{c}',ASCII码:{(int)c}"); }
如果文本文件的变量名长度更长,或者出现ASCII码为13的字符(\r),就坐实了隐藏字符的问题。
解决方案:标准化变量名
针对文本文件读取的变量名,我们需要做清理和标准化处理,确保去掉所有不可见的控制字符和空白:
1. 读取每行时直接清理
读取文本文件的每行后,用Trim()方法去除首尾的空白字符(包括\r、\n、空格、制表符等):
using (StreamReader reader = new StreamReader("你的文本文件路径")) { string line; while ((line = reader.ReadLine()) != null) { // 清理变量名:去除首尾所有空白和控制字符 string cleanedVarName = line.Trim('\r', '\n', ' ', '\t'); if (!string.IsNullOrEmpty(cleanedVarName)) { PlayerPrefs.SetString(cleanedVarName, variableValue); } } }
2. 统一处理整个文本的换行符
如果你的文本文件存在混合换行符的情况,可以先统一替换所有换行符为\n,再分割处理:
string fileContent = File.ReadAllText("你的文本文件路径"); // 把所有\r\n和\r替换为\n,统一换行格式 fileContent = fileContent.Replace("\r\n", "\n").Replace("\r", "\n"); string[] lines = fileContent.Split('\n'); foreach (string line in lines) { string cleanedVarName = line.Trim(); if (!string.IsNullOrEmpty(cleanedVarName)) { PlayerPrefs.SetString(cleanedVarName, variableValue); } }
3. 通用的变量名标准化方法
如果担心还有其他不可见控制字符,可以写一个通用方法过滤所有非打印字符:
private string NormalizePlayerPrefsKey(string input) { // 过滤所有控制字符,再去除首尾空白 return new string(input.Where(c => !char.IsControl(c)).ToArray()).Trim(); }
然后在设置PlayerPrefs前,用这个方法处理所有来源的变量名:
string varName = NormalizePlayerPrefsKey(从文本文件或手动获取的变量名); PlayerPrefs.SetString(varName, variableValue);
额外说明
PlayerPrefs对键名的匹配是完全精确的,哪怕一个不可见字符的差异都会被当作不同的键,这也是为什么你看到部分变量重复、部分不重复——那些不重复的变量对应的文本行刚好没有隐藏字符,而重复的行存在这类问题。
内容的提问来源于stack exchange,提问作者o Ak

