Hi guys, i got a little problem. I have a static instance of my AudioManager. Inside this script i have some functions to handle the audio, including MuteUnmuteMusic(). I have also a ui button inside the pause menu and i referenced this function to the onclick() of the music button (all from the inspector). The first time i run the game it’s all fine, when i reload the scene, the button lose the reference to that instance. The instance is still there. The AudioManager script also has DontDestroyOnLoad () inside Awake() because i won’t the music to restart on every level restart. Is it possible to keep the reference inside the ui button to this script or am i missing something?
These two things don’t have anything to do with each other. DontDestroyOnLoad() flags a root GameObject so that it does not get destroyed when the next scene loads.
If you properly implement a Unity singleton pattern, you want to NOT reload the AudioManager at all, including all the button hierarchy for it. But this gets mucky, keeping part of the UI around. Another way is to have an instance button “handler” script that has those references connected to it, and then have those functions forward your calls onto the actual singleton Audiomanager, and that (along with the buttons) gets unloaded and reloaded.
Alternately you can use a mechanism that only has the buttons change persistent variables (such as stored in PlayerPrefs) and do nothing else. Then it is the job of the AudioManager to pay attention (subscribe or just check each frame) to that status boolean.
My AudioManager script is this
public class AudioManager : MonoBehaviour {
public static AudioManager instance;
public static bool musicPlaying;
public AudioSource musicSource;
private bool musicMuted = false;
void Awake() {
if (instance == null) {
instance = this;
}
else if (instance != this) {
Destroy(gameObject);
}
if (!musicPlaying) {
instance.gameObject.GetComponentInChildren<AudioSource>().Play();
DontDestroyOnLoad(gameObject);
musicPlaying = true;
}
}
public void MuteMusic() {
musicMuted = !musicMuted;
instance.gameObject.GetComponentInChildren<AudioSource>().mute = musicMuted;
}
}
Is there something wrong? Anyway i tried with creating a script to handle the button, and then created all the functions that i need like MuteMusic() that calls AudioManager.instance.MuteMusic(). It works but i don’t get why. Because i can’t reference a static instance inside objects that get destroyed and then recreated like my ui button? Thank you
First of all, in line 18 above you should immediately return after destroying the object, otherwise you risk running the subsequent code on that doomed object.
When you change scenes, ALL things in the scene are reloaded. This means if you have something in there marked DontDestroyOnLoad() from the previous scene, you now have two copies of that thing. That’s what the line 15-17 check for, destroying any subsequent copies of this.
Meanwhile your script to handle the button has come in fresh, usually along with the button, and it can call the singleton above, as you observed.