Audio problem solved, but I've no idea why!!

I’ve figured out that PlayOneShot doesn’t work for collision sounds via OnCollisionEnter function if you have OTHER audioclips going through Update in a separate Audio function activated by user input via if statements. In this scenario, only input sounds will play.

Instead if I move the call to the Audio function away from update and into the input functions (which refer to Update anyway) it works… WHYYYY???

that makes no sense to me :eyes:

using UnityEngine;
using UnityEngine.SceneManagement;

public class Rocket : MonoBehaviour
{

    //Member variables
    Rigidbody rigidBody;

    [SerializeField] AudioClip Engine;
    [SerializeField] AudioClip Rotate;
    [SerializeField] AudioClip Die;
    [SerializeField] AudioClip winLevel;
    AudioSource audioSource;
   
   
    [SerializeField] float rcsThrust = 220f;
    [SerializeField] float mainThrust = 50f;
    [SerializeField] float upThrust = 50f;

    bool wonLevel = false;
    bool died = false;


    enum State {alive, dying, transcending};
    State state = State.alive;

    //[SerializeField] float rotateForce = 20f;

    // Start is called before the first frame update
    void Start()
    {
        rigidBody = GetComponent<Rigidbody>();
        audioSource = GetComponent<AudioSource>();
               
    }

    // Update is called once per frame
    void Update()
    { if (state == State.alive)
        {
            ThrustShip();
            RotateShip();
           
        }

        //Audio();    //IF I CALL AUDIO FUNCTION FROM HERE,
                            // THE "DIE" AND "WINLEVEL" SOUNDS WON'T PLAY

    }

    private void ThrustShip()
    {
        if (Input.GetKey(KeyCode.Space) )
        {
            rigidBody.AddRelativeForce(Vector3.up * mainThrust);
            rigidBody.AddForce(Vector3.up * upThrust);
            Audio();   //INSTEAD IF I CALL AUDIO FROM HERE EVERYTHING WORKS
        }
               
    }
    private void RotateShip()
    {
        rigidBody.freezeRotation = true;


        float rotationThisFrame = rcsThrust * Time.deltaTime;

        if (Input.GetKey(KeyCode.A))
        {

            transform.Rotate(Vector3.forward * rotationThisFrame);

        }
        else if (Input.GetKey(KeyCode.D))
        {
            transform.Rotate(-Vector3.forward * rotationThisFrame);

        }

        rigidBody.freezeRotation = false;
        Audio();  //FROM HERE WORKS TOO
    }


    void OnCollisionEnter(Collision collision)
    {

        if (state != State.alive)

        {
            return;
        }


        switch (collision.gameObject.tag)
        {
            case "Friendly":
                //do nothing
                break;

            case "Finish":
                state = State.transcending;
                             
                audioSource.Stop();
                audioSource.PlayOneShot(winLevel);
                Invoke("LoadNextScene", 5f);
                break;

            case "Untagged":
                state = State.dying;
                               
                print("playaudio");
                audioSource.Stop();
                audioSource.PlayOneShot(Die);   
                Invoke("LoadStartScene", 5f);
                break;


        }
    }

    private void LoadStartScene()
    {
        SceneManager.LoadScene(0);
    }

    private void LoadNextScene()
    {
        SceneManager.LoadScene(1);
    }



   
   
   
   
   
   
   
    void Audio()
    {
        if (Input.GetKey(KeyCode.Space) && state == State.alive && !audioSource.isPlaying)
        {
           
            audioSource.PlayOneShot(Engine);
        }

         if (Input.GetKeyUp(KeyCode.Space) ||  state == State.dying || state == State.transcending)
        {
            audioSource.Stop();
        }





       /* if (died == true && !audioSource.isPlaying )
        {

            print("dead");
            audioSource.Stop();
            audioSource.PlayOneShot(Die);          
            died = false;
           
        }*/

        if (Input.GetKeyDown(KeyCode.A) && state == State.alive)
        {
            audioSource.PlayOneShot(Rotate);
        }

        if (Input.GetKeyDown(KeyCode.D) && state == State.alive)
        {
            audioSource.PlayOneShot(Rotate);
        }


       /* if (wonLevel == true && !audioSource.isPlaying)

        {
            audioSource.PlayOneShot(winLevel);
            wonLevel = false;
                      
        }*/



    }

}

In your non-working scenario, it’s outside the “if (state == State.alive)” if statement. In the working scenarios, it’s inside that “if”. That’s the important difference.
You could call Audio() at line 44 here and it should work.

1 Like

That actually works, but I don’t understand how it affects the audio played from the OnCollisionEnter and NOT the audio that depends directly or indirectly from the update function.

It doesn’t matter when the audio started. It matters whether that is being run every frame because if it’s being run every frame it has a chance to interrupt whatever is playing. Most likely lines 150-152 would cause it to be interrupted.