Making a song play once when using bool variables

I’m having some issues with playing music when my game ends. Whenever the music starts playing, it starts over, causing the song to play continuously. Currently, I’ve set up my script so the music starts playing if the audio is not playing. However, I’m not sure how to check when the song has ended without resorting to the use of coroutines, which don’t work as well for how my script is set up currently. I’ve also tried using the PlayOneShot() function, but it has a similar result to before, except the song restarts much faster than just using the Play() function (making the music sound like it’s stuttering rapidly)

Here is the script I’m using to handle the game over music:

public class GameOverController : MonoBehaviour
{
    public bool gameEnded = false;
    public AudioClip gameOverMusic;

    GameObject player;
    bool gameRestarting = false;
    int playerScore;
    bool songPlaying = false;

    void Start()
    {
        GetComponent<GUITexture>().guiTexture.pixelInset = new Rect(0, 0, Screen.width, Screen.height);
        GetComponent<GUITexture>().guiTexture.enabled = false;
        GetComponent<GUIText>().enabled = false;

        player = GameObject.FindGameObjectWithTag(Tags.player);
    }

    void Update()
    {
        Debug.Log("Game ended: " + gameEnded);
        playerScore = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<PlayerScore>().score;
        if (gameEnded)
        {
            Destroy(player);
            SetToHalfColored();
            songPlaying = true;
            GameObject.Find("object-emitters").GetComponent<RandomSpawner>().enabled = false;
            GetComponent<GUIText>().enabled = true;
            GetComponent<GUIText>().text = "Final Score: " + playerScore;
        }

        if (songPlaying) {
            PlayGameOverMusic();
            //audio.Stop();
        }

        if (gameRestarting)
        {
            gameEnded = false;
            GetComponent<GUIText>().enabled = false;
            GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<SceneFadeInOut>().EndScene();
        }
    }

    void OnGUI()
    {
        if (gameEnded)
        {
            if (GUI.Button(new Rect((Screen.width / 2), (Screen.height / 2) - 70 / 2, 100, 30), "Replay"))
            {
                gameRestarting = true;
            }
        }
    }

    void SetToHalfColored()
    {
        GetComponent<GUITexture>().guiTexture.color =
            new Color(GetComponent<GUITexture>().guiTexture.color.r,
                GetComponent<GUITexture>().guiTexture.color.g,
                GetComponent<GUITexture>().guiTexture.color.b,
                .3f);
    }

    void PlayGameOverMusic() {
        if (!audio.isPlaying)
        {
            audio.clip = gameOverMusic;
            audio.Play();
        }
    }
}

If there is anyone who knows of a proper way to play the music only once, please let me know.

Your issue is here:

if (songPlaying) {
            PlayGameOverMusic();
            //audio.Stop();
        }

You can add a bool when you start playing the audio file and check against it in the Update function…There is quite of few ways you can handle this. Here is probably the easiest way to fix your problem.

private bool mhasPlayedGameOverMusic = false; //Add this to your class variables

void Update()
{
//....

if (songPlaying && mhasPlayedGameOverMusic == false) {
            PlayGameOverMusic();
            //audio.Stop();
        }

}

void PlayGameOverMusic() {
        if (!audio.isPlaying)
        {
            mhasPlayedGameOverMusic = true;
            audio.clip = gameOverMusic;
            audio.Play();
        }
    }