- Home /
Audio or Music to continue playing between scene changes
Is there a simple way to have audio like a background music track to carry over to another scene without stopping or restarting?
I've found a script similar but it was more like a jukebox and it was in C#, I'm still baby-stepping through Javascript.
what if that audio is still playing in the scene that doesnt require that audio.? How to stop it?
Answer by jashan · Feb 10, 2010 at 07:16 AM
What you'd probably do is attach the AudioClip to a game object to which you also have attached a script which calls DontDestroyOnLoad. That way, the game object does not get destroyed when the new scene is loaded and audio should keep playing.
EDIT: Of course, if you have that game object in every scene, it will duplicate the sound. One solution to that is following what I call the "Unity Singleton" pattern which is kind of like the classic Singleton pattern but specific to Unity (this is C# because I find examples easier to understand in C# - UnityScript follows right below):
public class MyUnitySingleton : MonoBehaviour {
private static MyUnitySingleton instance = null;
public static MyUnitySingleton Instance {
get { return instance; }
}
void Awake() {
if (instance != null && instance != this) {
Destroy(this.gameObject);
return;
} else {
instance = this;
}
DontDestroyOnLoad(this.gameObject);
}
// any other methods you need
}
What this basically does is: Check for an existing instance, if there already is an instances, destroy self - if not, store this is instance (so anyone who's coming later will destroy themselves). This also provides a public accessor so you can access the single instance from anywhere via MyUnitySingleton.Instance. Of course, you'd have your sound-specific methods also in that same class/script.
So here's (hopefully) the same in UnityScript (note that this must be in a file called "MyUnitySingleton" - or, in other words: replace any occurrence of "MyUnitySingleton" with the filename of your script):
private static var instance:MyUnitySingleton; public static function GetInstance() : MyUnitySingleton { return instance; }
function Awake() { if (instance != null && instance != this) { Destroy(this.gameObject); return; } else { instance = this; } DontDestroyOnLoad(this.gameObject); }
That's great, but now how do I get it to stop, not play again and overlap when the scene is reloaded, or the music track changes altogether? DonDestroyOnLoad works too well. :)
Ah, you probably have that same object in the scene your loading as well, right? In that case you need to make sure there's only one instance of the object. Do so by adding a static variable "instance" and assigning it on Awake(); also check if it already is assigned, and if it is - destroy the object.
when user go to setting and audio off and user quite a game then come audio off?
Still having a lot of trouble with this. I imagine the easiest way to set up a BG$$anonymous$$ system is to have a script identify a track being played. If it is the same, don't play the audio. If it is different, stop the existing one and play the new one. Then some how have this script on every scene so that the music is always correct for that scene no matter what. Then again this might be beyond my current skill level with Javascript.
I think I'll edit my original posting to contain some more specifics which will hopefully clarify things for you.
... the advantage of using the Singleton pattern as outlined above is that you don't have to worry about which song is played when switching a scene because there's not change in the audio when you do that. Of course, you need a separate mechanism of controlling which song is played (and you'd integrate that into this Singleton class ... you might call it $$anonymous$$usic$$anonymous$$anager or something like that).
Answer by Rimrook · Feb 26, 2010 at 07:46 AM
Ok, I've eventually answered my own question. For great justice, I'll post my findings for others to see/nab/yank/freeb. The code is simple to use, and extremely handy.
First, on your title screen or whatever is your first scene, add this script to a game object with an audio source. Name this game object "Game Music".
private static var instance:MyUnitySingleton; public static function GetInstance() : MyUnitySingleton { return instance; }
function Awake() { if (instance != null && instance != this) { Destroy(this.gameObject); return; } else { instance = this; } DontDestroyOnLoad(this.gameObject); }
(That bit of code was kindly provided by Jashan, thank you Jashan.) Create a new empty game object and add a "Music Manager" script to it.
Var NewMusic: AudioClip; //Pick an audio track to play.
function Awake () { var go = GameObject.Find("Game Music"); //Finds the game object called Game Music, if it goes by a different name, change this. go.audio.clip = NewMusic; //Replaces the old audio with the new one set in the inspector. go.audio.Play(); //Plays the audio. }
Have this Music Manager in your scenes. If it is different, it will change the music. If it is the same, it will keep playing and won't be interrupted by level loads or anything. To stop the music, use the Music Manager and select None for the audio. Alternatively, you can always tell the Game Music object to stop its audio to and all those commands that go with it. I suggest never really destroying it, this one object can set the music for your entire game.
I hope you like it.
I don't get the code. If you're declaring a singleton, why then go and grab your object by 'Find'? Could you not just access it by Gamemusic.singleton.whatever?
i followed the code and it works perfectly fine, but my question is as i couldnt understand the code and thus cant manipulate, what would i need to do to stop the game theme music for example wen the user reaches the main game playing level there needs to start a new music so at that particular game level id want that the main game music shall stop playing and this new music starts at the game level. i followed what rimrock suggested, the code of game music and music manager and it works fine, but my concern is that wen id built the game level and at that instance would want the main game music to stop playing and this new music plays in that game level only then what manipulations i would have to make to the code suggested by Rimrock of the game music and music manager script.
ATTENTION To everybody who's trying to implement this I suggest taking look at Reder13's answer on this link: [audio-or-music-to-continue-playing-between-scene][1]. It is done within few lines of code. The code above doesn't use singleton at all and did not work for me.
Peace [1]: http://answers.unity3d.com/questions/878382/audio-or-music-to-continue-playing-between-scene.html
Answer by RodrigoSeVeN · Jun 21, 2012 at 03:17 PM
I looked around for solutions, but none went out to do exactly what we really wanted. Consider you have only one object that can play the music and there will be no copies of it on the other scenes. Activate the Play On Awake and Loop check boxes. Here's my solution in simple JavaScript and I hope this is what you might be looking for.
So, consider you have an object called Jukebox with an AudioSource component in it. It's quite simple, all you need to do is keep track of the current time. Check this:
var currentMusicTime:float;
function Start(){
DontDestroyOnLoad(gameObject);
}
function Update(){
currentMusicTime=audio.time;
}
function OnLevelWasLoaded(lvl:int){
audio.time=currentMusicTime;
}
I'll post this on other similar threads, I hope it's ok to do so and I hope it helps!
how to stop the music in scenes that i dont want to play it in
That's what I was looking for. Actually, I used a combination of PlayerPrefs, Awake() and audio.time. Worked perfectly. Cheer brother.
Answer by Rimrook · Feb 19, 2010 at 05:00 AM
This is what I have so far, it doesn't seem to work. Instead of comparing audio tracks, it compares names. The surviving gameobject gets renamed to differentiate between the new music manager to the old one.
private static var instance:MusicManager;
public static function GetInstance() : MusicManager { return instance; }
function Awake() { if (instance != null && instance != this) { Destroy(this.gameObject); return; }
else
{
instance = this;
var GameMusic : GameObject = GameObject.Find("GameMusic");
var OldGameMusic : GameObject = GameObject.Find("OldGameMusic");
If (GameMusic)
{
Destroy(OldGameMusic);
}
}
this.gameObject.name = "OldGameMusic";
DontDestroyOnLoad(this.gameObject);
}
@script RequireComponent(AudioSource)
Tip: Edit it and clean it up. You're more likely to get people to actually read your code.
Answer by toddwilliams · Jan 23, 2012 at 02:41 AM
Rimrook left out a vital piece of the continuing music puzzle, an if statement. I believe the second set of code should look like this:
var NewMusic: AudioClip; //Pick an audio track to play.
function Awake () {
var go = GameObject.Find("Game Music"); //Finds the game object called Game Music.
if (go.audio.clip != NewMusic) {
go.audio.clip = NewMusic; //Replaces the old audio with the new one set in the inspector.
go.audio.Play(); //Plays the audio.
}
}
@Rimrook : i tried your script....i applied one script in main scene and second script(music manager scene) in all other scenes..it works fine in 4 scenes but it is not working in rest of the scenes..
i have applied audio source in main scene only...haven't applied it on rest of all the scenes. following is the first script.
private static var instance : musicscript;
public static function GetInstance() : musicscript {
return instance;
}
function Awake() {
if (instance != null && instance != this) {
Destroy(this.gameObject);
return;
} else {
instance = this;
}
DontDestroyOnLoad(this.gameObject);
}
here is the second script..
var New$$anonymous$$usic: AudioClip; //Pick an audio track to play.
function Awake ()
{
var go = GameObject.Find("Game $$anonymous$$usic"); //Finds the game object called Game $$anonymous$$usic, if it goes by a different name, change this.
go.audio.clip = New$$anonymous$$usic; //Replaces the old audio with the new one set in the inspector.
go.audio.Play(); //Plays the audio.
}
please help..