Using triggers to switch song currently playing in game

I’m having issues making a system where the background music changes whenever you enter a separate area. For example, if you move to the right side of a room the music should be different than what is playing on the left side of the room.

I currently have a system which uses two scripts: one that is attached to a global MusicManager game object and another connected to numerous triggers (which have AudioSource components attached) set around the room. What I hope to accomplish is this:

  • If no song is playing and player enters a music trigger, then play that music
  • If music is playing and player enters a music trigger, stop currently playing music and start new music (attached to currently entered trigger)

However, the system I have in place plays the song connected to each trigger without stopping the previous song from playing.

The main issue is coming from the script attached to each audio trigger, as it just plays the attached song whenever the player enters it. My initial design was to keep it simple, so that’s why it looks like this:

public class MusicSelect : MonoBehaviour {
 
    GameObject player;

    void Start() {
        player = GameObject.FindGameObjectWithTag("Player");
    }

    void OnTriggerEnter(Collider other) {
        if (other.gameObject == player) {
            audio.Play();
        }
    }
}

All of the major work was supposed to be handled by the MusicManager’s script, which would turn the volume down to 0 and switch the playing song to the one from the current audio trigger. Here’s the code for the MusicManager:

public class MusicManager : MonoBehaviour {
    public float musicFadeSpeed = 1.8f;
    GameObject[] musicTriggers;

    AudioSource currAudio, newAudio;
    static MusicManager instance = null;

    bool changingSongs = false;

    void Start()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            Destroy(this.gameObject);
        }

        musicTriggers = GameObject.FindGameObjectsWithTag("MusicTrigger");        
    }

    void Update() {
       
        MusicSelect selection = GameObject.FindGameObjectWithTag("MusicTrigger").GetComponent<MusicSelect>();        
        if(!selection.audio.isPlaying)
            currAudio = selection.audio;
    }

}

If anyone has any useful and relevant information about this problem, it would be much appreciated.

Here’s a method you could use:

Add an integer variable to your MusicSelect script that will reflect its current position in the musicTriggers array in MusicManager, as well as a reference to the actual musicmanager:

public class MusicSelect : MonoBehaviour {
int indexNumber=0;
GameObject musicManager; 
GameObject player;
//code

Then, in your MusicManager:

musicTriggers = GameObject.FindGameObjectsWithTag("MusicTrigger");
for(int i=0;i<musicTriggers.length;i++){
musicTriggers*.GetComponent<MusicSelect>().indexNumber=i;*

musicTriggers*.GetComponent().musicManager=this.gameObject;*
}
That should allow you to organise things better. Now enabling the audio clip from one of the triggers and disabling the rest is much more simple.
In MusicSelect, assuming musicManager is a gameobject variable that :
void OnTriggerEnter(Collider other) {
if (other.gameObject == player) {
musicManager.PlayAudio(indexNumber);
}
}
PlayAudio would be a function in the MusicManager that would take the ID of the trigger that was just triggered, enable its audio and disable the audio of the rest of them:

void PlayAudio(int indexNum){
for(int i=0;i<musicTriggers.length;i++)
musicTriggers*.audio.Stop();*
musicTriggers[indexNum].audio.Play();
}
(Although personally i would probably be only having one audiosource and be changing its audioClip via the triggers)