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

如何用Unity PlayerPrefs保存选项菜单音频设置并重启加载?

Unity音频设置无法通过PlayerPrefs保存的问题

我在Udemy课程中制作游戏功能菜单,音频设置环节卡壳了。课程推荐20db至-80db的线性音频刻度,但效果很差,换成对数刻度后音频稳定了,却遇到了设置保存问题——Unity的PlayerPrefs系统存不住音频设置,重启程序后之前的设置全没了。试了各种办法,还用上了Asset Store里的PlayerPrefs编辑器,还是找不到问题。我是Unity新手,求帮忙!

我的PlayerPrefs显示情况:
PlayerPrefs显示情况

以下是我的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;

public class OptionsMenu : MonoBehaviour
{
    public Toggle fullscreenTog, vsyncTog;

    public ResItem[] resolutions;

    private int selectedResolution;

    public TMPro.TextMeshProUGUI resolutionLabel;

    public AudioMixer theMixer;

    public Slider masterSlider, musicSlider, sfxSlider;
    public TMPro.TextMeshProUGUI masterLabel, musicLabel, sfxLabel;
    public float masterVolume, musicVolume, sfxVolume;

    public AudioSource sfxLoop;
    
    public 

    // Start is called before the first frame update
    void Start()
    {
        fullscreenTog.isOn = Screen.fullScreen;

        if(QualitySettings.vSyncCount == 0)
        {
            vsyncTog.isOn = false;
        }
        else
        {
            vsyncTog.isOn = true;
        }

        //search for resolution in list
        bool foundRes = false;
        
        for(int i=0; i < resolutions.Length; i++)
        {
            if(Screen.width == resolutions[i].horizontal && Screen.height == resolutions[i].vertical)
            {
                foundRes = true;

                selectedResolution = i;

                UpdateResLabel();
            }
        }

        if (!foundRes)
        {
            resolutionLabel.text = Screen.width.ToString() + " x " + Screen.height.ToString();
        }

        theMixer.SetFloat("MasterVol", Mathf.Log10(PlayerPrefs.GetFloat("MasterVol", 1) * 20));

    }

    // Update is called once per frame
    void Update()
    {
       
    }

    public void ResLeft()
    {
        selectedResolution--;
        if(selectedResolution < 0)
        {
            selectedResolution = resolutions.Length - 1;
        }

        UpdateResLabel();
    }

    public void ResRight()
    {
        selectedResolution++;
        if(selectedResolution > resolutions.Length - 1)
        {
            selectedResolution = 0;
        }

        UpdateResLabel();
    }

    public void UpdateResLabel()
    {
        resolutionLabel.text = resolutions[selectedResolution].horizontal.ToString() + " x " + resolutions[selectedResolution].vertical.ToString();
    }

    public void ApplyGraphics()
    {
        //apply fullscreen
        //Screen.fullScreen = fullscreenTog.isOn;

        if (vsyncTog.isOn)
        {
            QualitySettings.vSyncCount = 1;
        }
        else
        {
            QualitySettings.vSyncCount = 0;
        }

        //set resolution

        Screen.SetResolution(resolutions[selectedResolution].horizontal, resolutions[selectedResolution].vertical, fullscreenTog.isOn);

    }

    public void SetMasterVol(float sliderValue)
    {

        
        //masterLabel.SetText($"{sliderValue:F0)}");

        theMixer.SetFloat("MasterVol", Mathf.Log10(sliderValue) *20);
        
        
        PlayerPrefs.SetFloat("MasterVol", sliderValue);

        masterLabel.text = (sliderValue * 100).ToString("F0");

        
        
        PlayerPrefs.Save();
       
    }

    public void SetMusicVol()
    {
        musicLabel.text = (musicSlider.value * 100).ToString("F0");

        theMixer.SetFloat("MusicVol", Mathf.Log10(musicSlider.value) *20);

        PlayerPrefs.SetFloat("MusicVol", musicSlider.value);
    }

    public void SetSFXVol(float sliderValue)
    {
        sfxLabel.text = (sfxSlider.value * 100).ToString("F0");

        theMixer.SetFloat("SFXVol", Mathf.Log10(sliderValue) *20);

        PlayerPrefs.SetFloat("SFXVol", sliderValue);
    }

    public void PlaySFXLoop()
    {
        sfxLoop.Play(); 
    }

    public void StopSFXLoop()
    {
        sfxLoop.Stop();
    }

    
}

[System.Serializable]
public class ResItem
{
    public int horizontal, vertical;
}

问题排查与修复

1. 启动时未恢复所有音频设置

Start方法仅读取了Master音量的PlayerPrefs值,音乐和音效的音量未从本地存储读取,导致重启后这两项重置。替换原Start方法中的音频恢复代码:

void Start()
{
    // 原有分辨率、全屏、VSync代码保持不变...

    // 恢复Master音量
    float savedMaster = PlayerPrefs.GetFloat("MasterVol", 1f);
    theMixer.SetFloat("MasterVol", Mathf.Log10(savedMaster) * 20);
    masterSlider.value = savedMaster;
    masterLabel.text = (savedMaster * 100).ToString("F0");

    // 恢复Music音量
    float savedMusic = PlayerPrefs.GetFloat("MusicVol", 1f);
    theMixer.SetFloat("MusicVol", Mathf.Log10(savedMusic) * 20);
    musicSlider.value = savedMusic;
    musicLabel.text = (savedMusic * 100).ToString("F0");

    // 恢复SFX音量
    float savedSFX = PlayerPrefs.GetFloat("SFXVol", 1f);
    theMixer.SetFloat("SFXVol", Mathf.Log10(savedSFX) * 20);
    sfxSlider.value = savedSFX;
    sfxLabel.text = (savedSFX * 100).ToString("F0");
}

2. 部分音量设置未执行保存操作

SetMusicVol和SetSFXVol方法仅调用PlayerPrefs.SetFloat但未执行PlayerPrefs.Save(),数据可能无法写入本地存储。修改这两个方法:

public void SetMusicVol()
{
    musicLabel.text = (musicSlider.value * 100).ToString("F0");
    theMixer.SetFloat("MusicVol", Mathf.Log10(musicSlider.value) * 20);
    PlayerPrefs.SetFloat("MusicVol", musicSlider.value);
    PlayerPrefs.Save(); // 新增保存操作
}

public void SetSFXVol(float sliderValue)
{
    sfxLabel.text = (sliderValue * 100).ToString("F0");
    theMixer.SetFloat("SFXVol", Mathf.Log10(sliderValue) * 20);
    PlayerPrefs.SetFloat("SFXVol", sliderValue);
    PlayerPrefs.Save(); // 新增保存操作
}

3. 代码存在语法错误

代码中有一行无效的public 声明,会导致编译失败,直接删除该行即可。

额外验证点

  • 确保AudioMixer中暴露的参数名称("MasterVol"、"MusicVol"、"SFXVol")与代码中的字符串完全一致,Unity对字符串大小写敏感。
  • 可在PlayerPrefs.SetFloat后添加Debug.Log(PlayerPrefs.GetFloat("xxx")),打印并确认值是否正确写入。

内容的提问来源于stack exchange,提问作者Shadowfire638

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 20:15:55