Unity PlayerPrefs保存加载异常:音量正常,画质与视距重置
Unity设置菜单参数保存问题:画质与视距无法持久化
问题描述
我在Unity中制作了包含音量、视距、画质滑块的设置菜单,希望用PlayerPrefs保存这些参数,供玩家重启游戏时加载使用。目前音量参数保存正常,但画质等级和视距每次重启都会重置,程序无报错。
原代码
private void Start() { if(!PlayerPrefs.HasKey("musicVolume")) { PlayerPrefs.SetFloat("musicVolume",1); Load(); } else { Load(); } if (!PlayerPrefs.HasKey("qualityLevel")) { PlayerPrefs.SetInt("qualityLevel",6); Load(); } else { Load(); } if (!PlayerPrefs.HasKey("ViewDistance")) { PlayerPrefs.SetFloat("ViewDistance", 10); Load(); Debug.Log("saved viewdistance" + qualityslider.value * 1000); } else { Load(); } } private void Save() { PlayerPrefs.SetFloat("musicVolume", volumeslider.value); PlayerPrefs.SetInt("qualityLevel", QualitySettings.GetQualityLevel()); PlayerPrefs.SetFloat("ViewDistance", qualityslider.value); } private void Load() { volumeslider.value = PlayerPrefs.GetFloat("musicVolume"); qualityslider.value = PlayerPrefs.GetFloat("ViewDistance"); QualitySettings.SetQualityLevel(PlayerPrefs.GetInt("qualityLevel")); } public void ChangeVolume () { Save(); AudioListener.volume = volumeslider.value; } public void ChangeViewDistance() { Save(); Camera.main.farClipPlane = viewDistanceSlider.value * 1000; } public void ChangeQuality(float level) { //level = qualityslider.value; // QualitySettings.SetQualityLevel(level, false); switch((float)level) { case 0: QualitySettings.SetQualityLevel(0); // For lowest quality break; case 1: QualitySettings.SetQualityLevel(1); // For lowest quality break; case 2: QualitySettings.SetQualityLevel(2); // For lowest quality break; case 3: QualitySettings.SetQualityLevel(3); // For lowest quality break; case 4: QualitySettings.SetQualityLevel(4); // For lowest quality break; case 5: QualitySettings.SetQualityLevel(5); // For lowest quality break; case 6: QualitySettings.SetQualityLevel(6); // For lowest quality break; } }
问题根源
- 视距变量混淆:Save()中误将
qualityslider.value作为视距保存,Load()又把视距值赋给qualityslider,完全搞混了视距滑块(viewDistanceSlider)和画质滑块的关联。 - 画质修改未触发保存:ChangeQuality()只修改了QualitySettings,但从未调用Save(),导致新的画质等级根本没写入PlayerPrefs。
- Start()重复调用Load():三个if-else分支分别调用Load(),会导致参数被多次覆盖,逻辑冗余且可能引发异常。
- 视距修改逻辑顺序错误:ChangeViewDistance()先调用Save()再修改相机远裁剪面,导致保存的是旧值而非新设置的视距。
- ChangeQuality()的switch冗余:可以直接将传入的level转为整数调用SetQualityLevel,无需写7个重复的case。
修复后的代码
private void Start() { // 初始化默认值(仅当不存在时设置) if (!PlayerPrefs.HasKey("musicVolume")) PlayerPrefs.SetFloat("musicVolume", 1f); if (!PlayerPrefs.HasKey("qualityLevel")) PlayerPrefs.SetInt("qualityLevel", 6); if (!PlayerPrefs.HasKey("ViewDistance")) PlayerPrefs.SetFloat("ViewDistance", 10f); // 统一加载一次即可 Load(); } private void Save() { PlayerPrefs.SetFloat("musicVolume", volumeslider.value); PlayerPrefs.SetInt("qualityLevel", QualitySettings.GetQualityLevel()); // 修正:保存视距滑块的正确值 PlayerPrefs.SetFloat("ViewDistance", viewDistanceSlider.value); // 手动调用Save确保立即写入磁盘,避免意外丢失 PlayerPrefs.Save(); } private void Load() { volumeslider.value = PlayerPrefs.GetFloat("musicVolume"); // 修正:将视距值赋给对应的视距滑块 viewDistanceSlider.value = PlayerPrefs.GetFloat("ViewDistance"); QualitySettings.SetQualityLevel(PlayerPrefs.GetInt("qualityLevel")); // 加载后同步实时生效的参数 AudioListener.volume = volumeslider.value; Camera.main.farClipPlane = viewDistanceSlider.value * 1000; } public void ChangeVolume() { AudioListener.volume = volumeslider.value; Save(); } public void ChangeViewDistance() { Camera.main.farClipPlane = viewDistanceSlider.value * 1000; // 先修改值再保存,确保存的是最新值 Save(); } public void ChangeQuality(float level) { // 直接转换为整数设置画质等级,去掉冗余switch int qualityIndex = Mathf.RoundToInt(level); // 限制范围,防止滑块值超出画质等级的有效范围(0到QualitySettings.names.Length-1) qualityIndex = Mathf.Clamp(qualityIndex, 0, QualitySettings.names.Length - 1); QualitySettings.SetQualityLevel(qualityIndex); // 新增:修改后立即保存 Save(); }
额外注意事项
- 确保画质滑块的范围设置为0到
QualitySettings.names.Length-1,并勾选“Whole Numbers”,保证滑块值是整数,匹配画质等级的索引。 - PlayerPrefs.Save()会强制将数据写入磁盘,虽然Unity退出时会自动保存,但实时修改后调用能避免意外崩溃导致的参数丢失。
- 若测试时参数仍未保存,可以在Unity编辑器的
Edit > Clear PlayerPrefs清除旧数据后重新测试。
内容的提问来源于stack exchange,提问作者Coding_Goose
相关产品推荐
相关产品推荐

