0
\$\begingroup\$

I have game that plays music. I have a mute toggle button that will mute my game music when you press on it, it will also un-mute it when you press it again. I'm having problems with saving the audio volume when a scene is loaded. (I tried using DontDestoryOnLoad but my mute script is attach to my main menu canvas so its saving the canvas as well, which I do not want. I find using playerprefs a lot easier). For example, when I click on my mute button, it mutes my game, I play the game, die, restart the game and the volume is being restarted as well. Even though I used playerprefs to try and solve the problem it didn't work, it still did the same thing. Anyway this is my script:

public bool mute; 
public static Vector3 target;

void Start ()
{
    PlayerPrefs.GetFloat("mute");
}

void  Update()
{
    PlayerPrefs.GetFloat("mute");
}

private void Muted ()
{
    mute = !mute;
    if (mute) {
        gameObject.GetComponent<AudioSource> ().volume = 0;
        PlayerPrefs.SetFloat("mute", 0);
    }
    else
    {
        gameObject.GetComponent<AudioSource> ().volume = 1;
        PlayerPrefs.SetFloat("mute", 1);
    }
}
\$\endgroup\$
1
\$\begingroup\$

You are using the PlayerPrefs.GetFloat in update, which is a horrible idea.

I see that you have attached the script to a canvas. Instead, create a class called SoundManager. Have that attached to an empty gameobject in the intro scene that your game loads into. Make that a singleton and have a dontdestroyonload for this gameobject.

public class SoundManager : MonoBehaviour
{
    public static SoundManager instance;
    public bool mute{
        set{
            PlayerPrefs.SetFloat("muted", value ? 1 : 0);
        }
        get{
            return PlayerPrefs.GetFloat("muted", 0) == 0 ? false : true;
        }
    }
}

Then you can do a simple check on the toggle button click

SoundManager.instance.mute != SoundManager.instance.mute;

gameObject.GetComponent<AudioSource>().mute = SoundManager.instance.mute;
\$\endgroup\$
0
\$\begingroup\$

First of you'll have to create a class that encapsulates all game state varables that need to be saved/loaded , then you'll have to tag this class with [Serializable] , after that do the following :

[Serializable]
public class GameState
{
public int Volume;
public bool mute;
}

now create a class and add these two methods to it, and dont forgot to instantiate GameState and pass it to this class

public class GameSave : MonoBehaviour {
public GameState gm;
public void SaveData()
{
    if (!Directory.Exists("Saves"))
        Directory.CreateDirectory("Saves");

    BinaryFormatter formatter = new BinaryFormatter();
    FileStream saveFile = File.Create("Saves/save.binary");



    formatter.Serialize(saveFile, GameState);

    saveFile.Close();
}

public void LoadData()
{
    BinaryFormatter formatter = new BinaryFormatter();
    FileStream saveFile = File.Open("Saves/save.binary", FileMode.Open);

    gm = (GameState)formatter.Deserialize(saveFile);

    saveFile.Close();
}
}
\$\endgroup\$
0
\$\begingroup\$

You did not check and restore if the audio is mute or not.

void Start ()
{
    if(PlayerPrefs.GetFloat("mute") == 0)
    {
     gameObject.GetComponent<AudioSource> ().volume = 0;
    }
    else
    {
     gameObject.GetComponent<AudioSource> ().volume = 1;
    }
}
\$\endgroup\$
0
\$\begingroup\$

According to Unity's documentation:

https://docs.unity3d.com/ScriptReference/PlayerPrefs.GetFloat.html

public static float GetFloat(string key, float defaultValue = 0.0F);

Returns the value corresponding to key in the preference file if it exists. If it doesn't exist, it will return defaultValue.

What you need to do here is using GetFloat(key) to get the value that has been stored in the PlayerPrefs and assign it to AudioSource.volume.

Generally if you have values/references that are static (will not be modified), you can cache them in Start function for later use. And the update function is completely no need here.

As an example I rewrite you code as shown below:

public bool mute; 
private AudioSource audioSource;

void Start ()
{
    // at the beginning we cache the needed references and read volume value from playerPrefs
    audioSource = GetComponent<AudioSource> ();
    audioSource.volume = PlayerPrefs.GetFloat("mute",1f); // we pass 1 as default value if nothing's found
}

private void Mute (bool value)
{
    mute = value;
    var volume = mute ? 0f: 1f;
    if(audioSource )
         audioSource.volume = volume ;
    PlayerPrefs.SetFloat("mute", volume );
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.