[ SOLVED ] PlayerPrefs.Save for my Audio Problem

Hi,

I have the following script which I use within my settings menu : -

using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

public class settingsScreen : MonoBehaviour {

    [Header("AudioMixer Reference")]
    public AudioMixer mixer;

    [Header("Slider References")]
    public Slider masterSlider;
    public Slider musicSlider;
    public Slider soundFxSlider;

    public void masterVolumeChangeValue(float value)
    {
        mixer.SetFloat("volMaster", value);
        PlayerPrefs.SetFloat("volMaster", value);
        PlayerPrefs.Save();
    }

    public void musicVolumeChangeValue(float value)
    {
        mixer.SetFloat("volMusic", value);
    }

    public void soundFxVolumeChangeValue(float value)
    {
        mixer.SetFloat("volSoundFx", value);
    }

    public void closeSettings ()
    {
        gameObject.SetActive(false);
    }
}

Right now, I’m trying to save this information to PlayerPrefs, I’m currently testing with the Master Volume :

    public void masterVolumeChangeValue(float value)
    {
        mixer.SetFloat("volMaster", value);
        PlayerPrefs.SetFloat("volMaster", value);
        PlayerPrefs.Save();
    }

Question is, am I doing this part right ?

Also, I have my musicPlayer code :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class musicPlayer : MonoBehaviour {

    static protected musicPlayer s_Instance;
    static public musicPlayer instance { get { return s_Instance; } }

    void Awake() {
        if (s_Instance !=null)
        {
            Destroy(gameObject);
            return;
        }

        s_Instance = this;

        AudioListener.pause = false;

        PlayerPrefs.GetFloat("volMaster");

        GetComponent<AudioSource>().Play();
        DontDestroyOnLoad(gameObject);
    }
}

where I have used

        PlayerPrefs.GetFloat("volMaster");

to try and load my ā€˜saved’ master volume, I’m aware that this sort of stuff isn’t supposed to work within the Unity Editor, but subsequent external builds basically prove it doesn’t work at all, any pointers would be greatly appreciated ?

PlayerPrefs should work fine in the editor.

The problem here is that you’re retrieving the ā€œvolMasterā€ value, but then not doing anything with it. You need to assign it to something, or pass it as a parameter. For example,

masterVolumeChangeValue(PlayerPrefs.GetFloat("volMaster"));

Hmm, I’m still having a lot of problems with this : -

New settingScreen script, because my sliders were reset each time you went back into the settings screen, and so needing fixed :

using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

public class settingsScreen : MonoBehaviour {

    [Header("AudioMixer Reference")]
    public AudioMixer mixer;

    [Header("Slider References")]
    public Slider masterSlider;
    public Slider musicSlider;
    public Slider soundFxSlider;

    float currentMasterLevel;
    float currentMusicLevel;
    float currentSoundFxLevel;

    public void masterVolumeChangeValue(float value)
    {
        mixer.SetFloat("volMaster", value);
        PlayerPrefs.SetFloat("volMaster", value);
        PlayerPrefs.Save();
    }

    public void musicVolumeChangeValue(float value)
    {
        mixer.SetFloat("volMusic", value);
    }

    public void soundFxVolumeChangeValue(float value)
    {
        mixer.SetFloat("volSoundFx", value);
    }

    public void closeSettings ()
    {
        gameObject.SetActive(false);
    }

    void Start () {
        mixer.GetFloat("volMaster", out currentMasterLevel);
        Debug.Log("Current Master Volume : "+currentMasterLevel);
        masterSlider.GetComponent<Slider>().value = currentMasterLevel;

        mixer.GetFloat("volMusic", out currentMusicLevel);
        Debug.Log("Current Music Volume : "+currentMusicLevel);
        musicSlider.GetComponent<Slider>().value = currentMusicLevel;

        mixer.GetFloat("volSoundFx", out currentSoundFxLevel);
        Debug.Log("Current SoundFx Volume : "+currentSoundFxLevel);
        soundFxSlider.GetComponent<Slider>().value = currentSoundFxLevel;
    }
}

Anyhow, now I have

GetComponent<AudioSource>().volume = PlayerPrefs.GetFloat("volMaster");

I get no volume whatsoever, :frowning:

in the Start function I also added a new check to make sure PlayerPrefs has the key volMaster, and if not, apply it

it seems no matter which way, other than removing it all together, I get any volume at all !? For some reason, the save seems to 0 out the volume all together ?

Instead of:

        mixer.GetFloat("volMaster", out currentMasterLevel);

Use:

        currentMasterLevel = mixer.GetFloat("volMaster");

The second parameter in GetFloat is a default parameter, not an output.

I looked that up to check, but it does in fact have an out parameter when used with an AudioMixer. :slight_smile: I didn’t know that before. (reference: https://docs.unity3d.com/ScriptReference/Audio.AudioMixer.GetFloat.html)
Anyhow, because of the prior fix suggested here, playerprefs should be working.

Oh, I hadn’t realized that was the AudioMixer’s function.

So, I’ve rewritten my settings script, and this works much better now :

using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

public class settingsScreen : MonoBehaviour {

    [Header("AudioMixer Reference")]
    public AudioMixer mixer;

    [Header("Slider References")]
    public Slider masterSlider;
    public Slider musicSlider;
    public Slider soundFxSlider;

    public void masterVolumeChangeValue(float value)
    {
        mixer.SetFloat("volMaster", value);

        mixer.GetFloat("volMaster", out value);
        Debug.Log("Current volMaster Volume : "+value);

        PlayerPrefs.SetFloat("volMaster", value);
        PlayerPrefs.Save();
    }

    public void musicVolumeChangeValue(float value)
    {
        mixer.SetFloat("volMusic", value);

        mixer.GetFloat("volMusic", out value);
        Debug.Log("Current volMusic Volume : "+value);

        PlayerPrefs.SetFloat("volMusic", value);
        PlayerPrefs.Save();
    }

    public void soundFxVolumeChangeValue(float value)
    {
        mixer.SetFloat("volSoundFx", value);

        mixer.GetFloat("volSoundFx", out value);
        Debug.Log("Current volSoundFx Volume : "+value);

        PlayerPrefs.SetFloat("volSoundFx", value);
        PlayerPrefs.Save();
    }

    public void closeSettings ()
    {
        gameObject.SetActive(false);
    }

    void Start () {

        if (PlayerPrefs.HasKey("volMaster")) {
            masterSlider.GetComponent<Slider>().value = PlayerPrefs.GetFloat("volMaster");
        }

        if (PlayerPrefs.HasKey("volMusic")) {
            musicSlider.GetComponent<Slider>().value = PlayerPrefs.GetFloat("volMusic");
        }

        if (PlayerPrefs.HasKey("volSoundFx")) {
            soundFxSlider.GetComponent<Slider>().value = PlayerPrefs.GetFloat("volSoundFx");
        }
    }
}

However, I think my main problem lies in my musicPlayer.cs, every single time it runs, the volume is set to 0 ?

Now, my thinking, my sliders have a audiomixer range of between -80db and 0, so when the volume is loudest, the slider has a value of 0, could it be, that when saving my slider value, the volume is being read back in from the playerprefs as literally a value of 0, i.e. no volume ?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class musicPlayer : MonoBehaviour {

    static protected musicPlayer s_Instance;
    static public musicPlayer instance { get { return s_Instance; } }

    void Awake() {
        if (s_Instance !=null)
        {
            Destroy(gameObject);
            return;
        }

        s_Instance = this;

        AudioListener.pause = false;

        GetComponent<AudioSource>().volume = PlayerPrefs.GetFloat("volMaster", 1);

        GetComponent<AudioSource>().Play();
        DontDestroyOnLoad(gameObject);
    }
}

Seems I need to convert my slider value into a range of between 0 and 1 for the volume to work properly, at least by my thinking, any ideas ?

You’re thinking well:)

1 Like

That’s the trouble, I’m unable to think at all, it’s completely befuddling. :face_with_spiral_eyes:

Clearly I’m out of my depth here, I think I may just have be having a problem all together with ā€˜VOLUME’, maybe I shouldn’t be working with it all and instead somehow apply the mixer settings instead, I’ve noticed I can change the settings within my slide range, and the volume ā€˜AUDIBLY’ changes, but the volume slider on my AUDIOSOURCE does not, which suggests I need to reference something else all together ( i.e. tell it to use the mixer directly somehow ), call me perplexed…

Hm? If you change the audio source slider in the inspector, the volume doesn’t change? Is that what you’re saying?

No, it does change if I manually move it, however, the audioMixer controls the volume independently of this, if I change my scripted sliders, the volume changes audibly, but I’ve noticed the audiosource volume of my persistent theme music stays at 1. A picture tells a 1000 words, so :

You’'ll notice the audiosource volume is 1 in the top part of the image, then once I’m within the settings screens, even though I have changed the sliders and audibly changed the volume, the volume is still at 1, so maybe volume is the wrong value to target, I somehow need to tell my music audiosource to find the mixer value ( volMaster ) instead and apply that ( but not to volume ? ). :eyes:

Sorry, not sure. I’d check first by ensuring the variable for volume is between 0 and 1 and afaik the volume is adjustable. I’ve never used a mixer before, though, so I guess I can’t say for certain in that respect.
I hope you figure it out :slight_smile:

1 Like

ack, I’m sure I will, I usually just keep stabbing in the dark until something bleeds… :slight_smile:

removing the GetComponent().volume all together seems like I’m getting somewhere, which kind of works, but doesn’t respect the playerprefs volume setting, it’s always highest volume, :face_with_spiral_eyes: , stab, stab, stab…

PlayerPrefs.GetFloat("volMaster");

Did ya ever try just like choosing 2 keycodes:

if(Input.GetKeyUp(KeyCode.G)) GetComponent<AudioSource>().volume -= .1f;
else if (Input.GetKeyUp(KeyCode.H)) GetComponent<AudioSource>().volume += .1f;

I dunno… just to see that it does something in code and narrow the problem. *Testing only, for sure… heh

Maybe I’ll see an update when I’m back after some sleep. Take it easy, good luck :wink:

Finally… :stuck_out_tongue:

This ā€˜almost’ seems like it’s working now, but it appears to have hi lighted another problem, when I go back into the settings menu, I get a half reduction in overall volume, oh, well, onwards… :sweat_smile:

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

public class musicPlayer : MonoBehaviour {

    static protected musicPlayer s_Instance;
    static public musicPlayer instance { get { return s_Instance; } }

    void Awake() {
        if (s_Instance !=null)
        {
            Destroy(gameObject);
            return;
        }

        s_Instance = this;

        AudioListener.pause = false;

        if (PlayerPrefs.HasKey("volMaster")) {
           
            float currentVolMaster = PlayerPrefs.GetFloat("volMaster",1);

            // Decibel to Linear calculation
            currentVolMaster = Mathf.Pow(10.0f, currentVolMaster / 20.0f);

            Debug.Log("currentVol :"+currentVolMaster);

            GetComponent<AudioSource>().volume = currentVolMaster;
        }

        GetComponent<AudioSource>().Play();
        DontDestroyOnLoad(gameObject);
    }
}

Glad to hear you made some progress. It’s odd you get a half reduction. Maybe you will track that down, too :slight_smile:

Ok, more investigation

first up, my code for starting my main music :

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

public class musicPlayer : MonoBehaviour {

    static protected musicPlayer s_Instance;
    static public musicPlayer instance { get { return s_Instance; } }

    void Awake() {
        if (s_Instance !=null)
        {
            Destroy(gameObject);
            return;
        }

        s_Instance = this;

        if (PlayerPrefs.HasKey("volMusic")) {

            float currentVolMusic = PlayerPrefs.GetFloat("volMusic");
            // Decibel to Linear calculation
            currentVolMusic = Mathf.Pow(10.0f, currentVolMusic / 20.0f);
            Debug.Log("currentVolMusic :"+currentVolMusic);

            GetComponent<AudioSource>().volume = currentVolMusic;
        }

        AudioListener.pause = false;
        GetComponent<AudioSource>().Play();

        DontDestroyOnLoad(gameObject);
    }
}

Now, I’ll try explain this as easy as I can, so I can ask the community for any help.

  1. first run of game, music starts at 0 dB ( basically 100% volume )
  2. I then go into my settings menu, adjust the volume -25 db ( basically reduce by 75% )
  3. This is all saved into PlayerPrefs file, I can go in and out of the settings menu as many time as I want, and this is working

NOW :

  1. Quit game all together, then run game again, we now have ā€˜SAVED’ PlayerPrefs
  2. Main music definitely plays at ā€˜correct’ ā€˜saved’ volume using value from ā€˜saved’ PlayerPrefs
  3. However, if i go into settings menu again, overall music volume halves

Here’s screenshots breaking this down, I can see what the problem is, I just don’t know how to fix it ? Please help ?

FIRST RUN :

SECOND RUN :

So,
it seems I pass my volume value to the AudioSource().volume component, but the AudioMixer volume remains at 0, so it seems like I need to pass that value to the audiomixer at the start instead of the volume, yeah ? Any ideas how I go about that ?

SOLVED !
That was ā€˜much’ more difficult than it needed to be, final code :

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

public class musicPlayer : MonoBehaviour {

    static protected musicPlayer s_Instance;
    static public musicPlayer instance { get { return s_Instance; } }

    [Header("AudioMixer References")]
    public UnityEngine.Audio.AudioMixer musicMixer;
    public UnityEngine.Audio.AudioMixer soundFxMixer;

    void Awake() {
        if (s_Instance !=null)
        {
            Destroy(gameObject);
            return;
        }
        s_Instance = this;

        AudioListener.pause = false;

        DontDestroyOnLoad(gameObject);
    }

    void Start()
    {
        if (PlayerPrefs.HasKey("volMusic")) {
            // Update volMusic volume slider from PlayerPrefs
            musicMixer.SetFloat ("volMusic", PlayerPrefs.GetFloat("volMusic"));

            float currentVolMusic = PlayerPrefs.GetFloat("volMusic");

            GetComponent<AudioSource>().volume = currentVolMusic;
        }

        if (PlayerPrefs.HasKey("volSoundFx")) {
            // Update volSoundFx volume slider from PlayerPrefs
            soundFxMixer.SetFloat ("volSoundFx", PlayerPrefs.GetFloat("volSoundFx"));
        }
           
        GetComponent<AudioSource>().Play();

        DontDestroyOnLoad(gameObject);
    }
}

and the settings menu code, excuse the other references in the code…

using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;

public class settingsScreen : MonoBehaviour {

    [Header("AudioMixer References")]
    public UnityEngine.Audio.AudioMixer musicMixer;
    public UnityEngine.Audio.AudioMixer soundFxMixer;

    [Header("Slider References")]
    public Slider musicSlider;
    public Slider soundFxSlider;

    [Header("Credits Screen Reference")]
    public GameObject creditsScreen;

    [Header("Privacy Screen Reference")]
    public GameObject privacyScreen;

    AudioSource musicSource;

    private void Awake ()
    {
        if (PlayerPrefs.HasKey("volMusic")) {
            float playerPrefsMusicValue = PlayerPrefs.GetFloat("volMusic");
            Debug.Log("Player Prefs Music Volume In Linear : "+playerPrefsMusicValue);

            // Convert Linear To Decibels
            playerPrefsMusicValue = 20.0f * Mathf.Log10(playerPrefsMusicValue);
            Debug.Log("Player Prefs Music Volume In Decibels : "+playerPrefsMusicValue);

            musicSlider.GetComponent<Slider>().value = playerPrefsMusicValue;

        }  else { musicSlider.GetComponent<Slider>().value = 0; }

        if (PlayerPrefs.HasKey("volSoundFx")) {
            float playerPrefsSoundValue = PlayerPrefs.GetFloat("volMusic");
            Debug.Log("Player Prefs Sound Volume In Linear : "+playerPrefsSoundValue);

            // Convert Linear To Decibels
            playerPrefsSoundValue = 20.0f * Mathf.Log10(playerPrefsSoundValue);
            Debug.Log("Player Prefs Sound Volume In Decibels : "+playerPrefsSoundValue);

            soundFxSlider.GetComponent<Slider>().value = PlayerPrefs.GetFloat("volSoundFx");
        }  else { soundFxSlider.GetComponent<Slider>().value = 0; }
    }

    public void musicVolumeChangeValue(float value)
    {
        musicMixer.SetFloat("volMusic", value);

        musicMixer.GetFloat("volMusic", out value);
        Debug.Log("Music Volume in Decibels : "+value);

        value = Mathf.Pow(10.0f, value / 20.0f);
        Debug.Log("Current Volume Of Music in Linear : "+value);

        musicSource = GameObject.FindGameObjectWithTag("musicPlayer").GetComponent<AudioSource>();
        musicSource.volume = value;
           
        PlayerPrefs.SetFloat("volMusic", value);
        PlayerPrefs.Save();
    }

    public void soundFxVolumeChangeValue(float value)
    {
        soundFxMixer.SetFloat("volSoundFx", value);

        soundFxMixer.GetFloat("volSoundFx", out value);
        Debug.Log("Sound Volume in Decibels : "+value);

        PlayerPrefs.SetFloat("volSoundFx", value);
        PlayerPrefs.Save();
    }

    public void creditsScreenActive ()
    {
        creditsScreen.SetActive(true);
    }

    public void privacyScreenActive ()
    {
        privacyScreen.SetActive(true);
    }

    public void closeSettings ()
    {
        gameObject.SetActive(false);
    }
}

Awesome. Glad to see you solved it. It kinda looks very similar to me :wink: But I’m glad ya got it.
I think you could even shorten the second script, because if the key is not found, you get ā€˜0’ (zero) for ā€œfreeā€ :slight_smile:
But that makes no real difference. :slight_smile:

1 Like