Play a list of tracks in random order

Hi

I want to play a list of music tracks in random order right from the start of the game. Here is what I get so far…

var music : AudioClip [];
function Start () 
{
if(!audio.playOnAwake) 
{
audio.clip = music[Random.Range(0,music.length)];
audio.Play();
audio.loop = true;
}
}

So it does pick a random track to play, but when that track is finished, it doesn’t play the next random one, it just repeat that track.

Help me please :slight_smile:

Thanks!

How/when does "music" array get populated? (Edit: Just drag/drop tracks into the exposed array via Unity editor)

8 Answers

8

You can do something like this, once the song finishes it will play another one at random:

void PlayNextSong(){
    audio.clip = music[Random.Range(0,music.length)];
    audio.Play();
    Invoke("PlayNextSong", audio.clip.length);
}

it’s because it’s never picking a new value for random range, it’s only called once in start

so what should I do now?

Try writing something in Update(). Clue: don't loop, check if still playing before playing a new one.

I don't think that the Update will work. Just tried it and the sound can not be played, just some weird sound. I think this is because Update is called every second?

//This is my version of Audio Playlist.

using UnityEngine;
using System.Collections;

public class MusicBg : MonoBehaviour {

private static MusicBg instance = null;
public AudioClip[] musicbg;
private int i;
	
	
	public static MusicBg Instance
	{
        get { return instance; }
    }
	
	
    void Awake() {
        if (instance != null && instance != this) {
            Destroy(this.gameObject);
            return;
        } else {
            instance = this;
        }
        DontDestroyOnLoad(this.gameObject);
    }
 
    void Start()
	{
	i= Random.Range(0,musicbg.Length);
	StartCoroutine("Playlist");
	}
	
IEnumerator Playlist()
	{
		while(true)
		{
			yield return new WaitForSeconds(1.0f);
			if(!audio.isPlaying)
			{
				if(i != (musicbg.Length -1))
				{
					i++;
					audio.clip = musicbg*;*
  •  			audio.Play();*
    
  •  		}*
    
  •  		else*
    
  •  		{*
    
  •  			i=0;*
    

_ audio.clip= musicbg*;_
_
audio.Play();_
_
}_
_
}_
_
}_
_
}_
_
}*_

DId you apply the script to the main camera? or was it to just an audio source in the map itself?

If I walk it stops playing of that song, any ideas how to fix?

Ahh fixed it.. Np anymore

This is what i’ve learned from this page, it is in c# btw :

using UnityEngine;
using System.Collections;

public class RandomAudio : MonoBehaviour
{
	public AudioClip[] soundtrack;

	// Use this for initialization
	void Start ()
	{
		if (!audio.playOnAwake)
		{
			audio.clip = soundtrack[Random.Range(0, soundtrack.Length)];
			audio.Play();
		}
	}
	
	// Update is called once per frame
	void Update ()
	{
		if (!audio.isPlaying)
		{
			audio.clip = soundtrack[Random.Range(0, soundtrack.Length)];
			audio.Play();
		}
	}
}

it is very simple yet it works it loops between the different numbers i have just tried it out and it works fine!
use if you like :smiley:

dude thx.. ppl just be careful about your script name and class name must match EXACTLY, including capital letters, spaces, etc.

They also can't have spaces.

var Musics : AudioClip;
var currentM = 0;
var mMusic : AudioClip;
var mNextMusic : AudioClip;
var MusicP : AudioSource;
//var MusicTime = 100;

function Start () {
	
	if (currentM >= Musics.length) currentM = Musics.length-1;
	/*for (var i=0; i<Musics.length; i++)
	DisableMusic(Musics*);*

_ */_

  • SelectMusic(Musics[currentM]);*
    }
    function Update () {

  • var IN = Input.GetButtonDown(“Music”);*

  • if(IN )//||MusicP.time>MusicTime)*

  • {*

  •  SwitchMusic(1);*
    
  • }*

  • MusicP.clip = mMusic;*

  • if(this.ignoreListenerVolume){}*

  • }*

  • function SwitchMusic (iDir : int)*

  • {*

  •  if (Musics.length < 2) return;*
    
  •  currentM += Mathf.Sign(iDir);*
    
  •  if (currentM < 0) currentM = Musics.length-1;*
    
  •  else if (currentM >= Musics.length) currentM = 0;*
    
  •  SelectMusic(Musics[currentM]);*
    
  •  MusicP.Play();*
    
  • }*

  • function SelectMusic(Music : AudioClip)*

  • {*

  •  if (mMusic)*
    
  •  {*
    
  •  	mNextMusic = mMusic;*
    
  •  }*
    
  •  mMusic = Music;*
    
  •  //MusicP.Play();*
    
  • }*

here’s my version in C# - I did this so I could invoke it to play in a google cardboard vr application upon looking at (clicking ) a GameObject. Hope this helps someone.

public class MusicPlaylist : MonoBehaviour
{

    //the gameObject that will play the music
    public AudioSource myMusic;
    public bool isOn = false;

    //allow other scripts to call functions from SoundManager
    public static MusicPlaylist instance = null;

//or however long your playlist is
    public AudioClip[] songList = new AudioClip[3];

    public int randomIndex = 0;

    void Awake()
    {
        //check if there is already an instance of SoundManager
        if (instance == null)
            instance = this;
        else if (instance != this)
            Destroy(gameObject);

        //so music continues between levels if desired
        DontDestroyOnLoad(gameObject);
    }

    //play a single audio clip / audio effect
    public void playSingle(AudioClip clip)
    {
        myMusic.clip = clip;
        myMusic.Play();
    }

    //play a random selection from a playlist
    public void playRandomSong()
    {
        randomIndex = Random.Range(0, songList.Length);
        myMusic.clip = songList[randomIndex];
        myMusic.Play();
        Invoke("playRandomSong", myMusic.clip.length);
    }

    public void turnOnOff()
    {
        if (isOn)
        {
            myMusic.Stop();
            isOn = false;
        }
        else
        {
            playRandomSong();
            isOn = true;
        }
    }


}

Hi, I was wondering if there is any way to read in the array length from "song List - Size" in the audio object that this script is attached to in Unity, so if someone changes the size of the array in the inspector before runtime the size of the array is updated at runtime. Thanks, Matt.

This is my version of @davem250 script

using System.Collections.Generic;
using UnityEngine;

public class MusicPlayer : MonoBehaviour {

public List<AudioClip> soundtrack;
AudioSource mySource;
private void Awake()
{
    mySource = gameObject.GetComponent<AudioSource>();
}
void Start()
{
    if (!mySource.playOnAwake)
    {
        mySource.clip = soundtrack[Random.Range(0, soundtrack.Count)];
        mySource.Play();
    }
}

// Update is called once per frame
void Update()
{
    if (!mySource.isPlaying)
    {
        mySource.clip = soundtrack[Random.Range(0, soundtrack.Count)];
        mySource.Play();
    }
}

}

Hi Guys, here’s an updated version of the script for this thread :

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RandomAudioPlaylistLoop : MonoBehaviour
{
public AudioClip soundtrack;

// Use this for initialization
void Start()
{
    if (!GetComponent<AudioSource>().playOnAwake)
    {
        GetComponent<AudioSource>().clip = soundtrack[Random.Range(0, soundtrack.Length)];
        GetComponent<AudioSource>().Play();
    }
}

// Update is called once per frame
void Update()
{
    if (!GetComponent<AudioSource>().isPlaying)
    {
        GetComponent<AudioSource>().clip = soundtrack[Random.Range(0, soundtrack.Length)];
        GetComponent<AudioSource>().Play();
    }
}

}

Let me know if something should be modified.