You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:15:33