Hello! I have a problem. In my game, when I am on my Main Menu Scene and trying to load Main Game Scene with Play button it plays the main menu background music continuously, where I dont want that to happen to more than 1 scene my options scene. When I am pressing options button and load options scene I want to hear that music of main menu to be played on options scene only and not when transitioning between main menu scene and main game scene. On my main game scene I have another scene and I hear it twice like my main game music and main menu music that still persist across all of my scenes when I am loading them.
Hi!
The simplest way to work around that problem is to ensure you manually destroy the gameobject playing the background music when you are moving to the scene where you want the audio to change.
Depending on how you set the DontDestroyOnLoad
there might be some nuances, but in general, you can provide a method within the object’s script to destroy it in a controlled way.
I say “controlled way” because a direct destruction can cause an abrupt cut in the current music being played, so you might want to apply some crossfade effect to make the audio transition seamless.
Tell me how to do that? I really can’t understand how to make it work only for a single scene and destroy it when load another scene for example main scene
There are multiple ways to approach what you need, so I’ll try to give an example general enough so you can adapt it to your actual flow.
Let’s say that you have a gameobject playing the menu music, and that gameobject has a script MenuBackgroundMusic
that keeps it alive by using DontDestroyOnLoad
.
Besides all the code in that script, you can include a public method to trigger a controlled self destruction.
For example, you could do:
public void DestroySelf()
{
Destroy(gameObject);
}
That’s the bare minimum. Whenever you are switching to the main scene, you can call that method. If your MenuBackgroundMusic
is a singleton, awesome, because you can call MenuBackgroundMusic.Instance.DestroySelf()
directly. If not, you’d need to have a reference to the instance of MenuBackgroundMusic
in whatever script you use to load the new scene.
For a smooth transition, calling Destroy(gameobject)
wouldn’t help
Instead, you’d need to plan a fade-out effect.
Here is a different version of the DestroySelf
, where you fade-out the menu music using a coroutine:
// Number of seconds to complete the fade-out, if you want
[SerializeField] float fadeOutDuration = 2.0f;
AudioSource _audioSource;
void Awake()
{
_audioSource = GetComponent<AudioSource>();
}
public void DestroySelf()
{
StartCoroutine(FadeOutAndDestroy());
}
IEnumerator FadeOutAndDestroy()
{
float startVolume = audioSource.volume;
while (audioSource.volume > 0)
{
audioSource.volume -= startVolume * Time.deltaTime / fadeOutDuration;
yield return null;
}
// If you want to keep the gameobject alive after the fade-out...
audioSource.Stop();
audioSource.volume = startVolume;
// If you prefer to destroy it...
Destroy(gameobject);
}
With the above code, your menu music would fade-out during 2 seconds before either stopping the audiosource or destroying it completely.
You could use additive scene loading. Load and unload scenes in script. Have some master scene that is always loaded and contains permanent stuff and a controller that controls other scene loading.
To start a game from another scene in editot, just add some object that checks if the master scene is loaded, and load it if not.