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

