Hi, how would I code it so that on the splash screen the element 0 in the array would play, because at the moment it doesn’t play, I know a fix without code but I prefer to code it in, thanks.
Hi,
What do you have in your MusicManager at the moment? Can you post the code please.
See also;
- Forum User Guides : How to apply code formatting within your post
At the moment it only plays from the next screen that loads.
public AudioClip[] levelMusicChangeArray;
private AudioSource backgroundMusic;
void Awake() {
DontDestroyOnLoad(gameObject);
}
// Use this for initialization
void Start () {
backgroundMusic = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update () {
}
void OnLevelWasLoaded(int level) {
AudioClip thisLevelMusic = levelMusicChangeArray[level];
Debug.Log("Playing clip: " + thisLevelMusic);
if(thisLevelMusic) { //If there's some music attached
backgroundMusic.clip = thisLevelMusic;
backgroundMusic.loop = true;
backgroundMusic.Play();
}
}
You could use the OnEnable
method and call a delegate;
using UnityEngine;
using UnityEngine.SceneManagement;
public class MusicManager : MonoBehaviour
{
public AudioClip[] levelMusicChangeArray;
private AudioSource audioSource;
/// <summary>
/// Pre-Initialisation
/// </summary>
private void Awake()
{
DontDestroyOnLoad(gameObject);
}
/// <summary>
/// Initialise
/// </summary>
void Start()
{
audioSource = gameObject.GetComponent<AudioSource>();
audioSource.volume = PlayerPrefsManager.GetMasterVolume();
}
/// <summary>
/// Called when the object becomes enabled and active
/// </summary>
void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
/// <summary>
/// Called when the object becomes disabled or inactive.
/// </summary>
void OnDisable()
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
/// <summary>
/// Plays music on level change
/// </summary>
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
AudioClip thisLevelMusic = levelMusicChangeArray[scene.buildIndex];
if (thisLevelMusic) // if there's some music attached
{
audioSource.clip = levelMusicChangeArray[scene.buildIndex];
audioSource.loop = true;
audioSource.Play();
}
}
/// <summary>
/// Changes the volume of the music
/// </summary>
public void SetVolume(float volume)
{
audioSource.volume = volume;
}
}
The above is taken from a Unity 5+ script, it may need a few tweaks if you are using a version lower than Unity 5. Let me know if this is the case.
Hope this helps.
See also;
Unity - Manual : Execution Order of Event Functions
I’m using Unity 5 onwards, but could you explain what the code is doing so I understand it, thanks.
Great, and sure, no problem.
So, if you look at the link I gave you you will see the execution order and repetition of events which occur during a scripts life time.
At the beginning you will note OnEnable
occurs during the script’s initialisation.
In the code example I gave you you will see that we use the OnEnable
method with the following code;
/// <summary>
/// Called when the object becomes enabled and active
/// </summary>
void OnEnable()
{
SceneManager.sceneLoaded += OnSceneLoaded;
}
Here we add our delegate (another method) to the SceneManager’s sceneLoaded variable.
When a scene is loaded, the methods added to this variable will be called in turn. Note, we are only providing the name of the method here, and do not add the parentheses on the end of it. e.g. OnSceneLoaded
not OnSceneLoaded()
.
When you add delegates, you should always clear up after yourself, as such, there is an OnDisabled
method which removes the delegate. As you can see from the order of event functions page, OnDisable
is called when either the script is disabled, or, during decommissioning.
The method which handles the playing of the audio clips if believe is similar to what you already have and probably doesn’t need al of explanation, it is merely using the scene’s build index value to return a specific element from the audio clip array (levelMusicChangeArray).
The buildIndex values are zero-based, e.g. your very first scene should have an index of 0 (zero).
The main difference between the two approaches is that using OnLevelWasLoaded
occurs after the level has loaded, by which point you are sending the player off to the menu. In the above, the music should start as soon as OnEnable
is called, or very, very soon after
I haven’t covered the other aspects of the script as they should be fairly familiar to you based on the version you posted. Any queries let me know.
See also;
- Unity - Scripting API : SceneManager.sceneLoaded
Thanks and sorry I didn’t notice the link you gave me, also just for more clarification how come my current code doesn’t work as it is since the first scene index is 0 and the array starts at 0.
I will take a look at the docs you left me too, thanks.
You’re welcome.
It’s not to do with the value of the build index, in both cases, as you have mentioned, it is 0 (zero). It is to do with the point in time at which the instruction to play the music occurs. I believe in the case of the example I gave, it should happen almost immediately, whereas with the code you posted previously, it happens after the scene is loaded. But, after this scene has loaded, the next scene is loading. The music player is then instructed to load the audio clip for that scene (scene 1), thus, you don’t hear the music for scene zero.
Without having the full project here to test/play with it’s a little hard to be precise, but the above would be my best suggestion.
Ahh, this is confusing me so much . I looked through the code you gave me, I added the OnEnable/OnDisable but the OnSceneLoaded part is different and the method itself for mine takes an int, but yours doesn’t.
I understand what OnEnable/Disable do but the rest throws me off.
Sorry, my intention was not to confuse you. Delegates are covered later in the course.
Those differences between the methods…
Yours takes in an int
which you then use as the build index of the scene. e.g it’s effectively saying “this was the index of the level that was loaded”.
AudioClip thisLevelMusic = levelMusicChangeArray[level];
Mine passes in a reference to the actual scene, it then uses the build index taken directly from the scene, e.g. it’s effectively saying “this is the index of the scene that is loaded”.
AudioClip thisLevelMusic = levelMusicChangeArray[scene.buildIndex];
It’s not your fault, I’ve found many things confusing it just takes a certain way of explaining it for me to twig it haha.
void OnLevelWasLoaded(int level)
{
AudioClip thisLevelMusic = levelMusicChangeArray[level];
Debug.Log("Playing clip: " + thisLevelMusic);
if (thisLevelMusic)
{ //If there's some music attached
backgroundMusic.clip = thisLevelMusic;
backgroundMusic.loop = true;
backgroundMusic.Play();
}
}
So I change this to this?;
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
AudioClip thisLevelMusic = levelMusicChangeArray[scene.buildIndex];
if (thisLevelMusic) // if there's some music attached
{
audioSource.clip = levelMusicChangeArray[scene.buildIndex];
audioSource.loop = true;
audioSource.Play();
}
}
However, when I did the above, it wasn’t allowing me to use OnSceneLoaded, so do I keep it as OnLevelWasLoaded but with (Scene scene, LoadSceneMode mode)?
Hi,
When you say “it wasn’t allowing me to use OnSceneLoaded”, what happened? Did you get an error?
I suspect elsewhere in your code you have a call to the previous method, e.g. OnLevelWasLoaded
?
Note the (Scene scene, LoadSceneMode mode)
is part of the method signature. Whilst the specific method name could be what ever you want (as long as you pass that to the onSceneLoaded
variable of the SceneManager, this does expect a method with this signature.
If you can give me some addition details, perhaps a screenshot of the error I would be grateful.
Oh it’s working now, not sure what the issue was haha.
Glad you have got it sorted - well done
I meant the OnLevelWasLoaded is working, however even with simply copying your code it’s not causing the audio to start.
If you can zip up the entire project and share it via Dropbox or perhaps Google Drive I will happily take a quick look for you.
I’m not familiar with google drive, I uploaded it to google drive but now how would I get it to you?
You should be able to share it via the URL, probably an option for the link etc… I don’t need any special permissions, it can just be public (assuming its a copy zipped up etc).
If you have other means, it doesn’t have to be only by those. The forum will only handle a 10mb file though, so invariably Glitch Garden tends to be too big to share via an upload.