0
\$\begingroup\$

Ok so when my player hits a wall (Enemy tag). My player is destroyed after a certain amount of time. During this time, I disabled the mesh renderer on impact so it "appears" as if the player is destroyed.

I have some sounds I want to play upon impact. One is 'game over" sound and one is an "explosion sound".

right now, when they play at the same time, they interfere with each other, causing the game over not to be heard correctly.

I wanted to delay the output of "game over" by 3 seconds. So the explosion is over. Play the 'Game over sound' and then destroy the player.

This is my code so far, but the compiler tells me that now OnTriggerEnter cannot be an iterator block now that I have a yield function. Is there any way to just delay the output of the game over sound without creating a whole new function for the game over sound and using Play Delayed?

and if I do have to use Play delayed, how do I set the volume of the sound? as right now I am using PlayOneShot

     // function to detect whether collision is with a pick-up cube or an emeny wall.
void OnTriggerEnter(Collider other)
{
    if (other.gameObject.CompareTag("PickUp"))
    {
        // if pick-up object. Pick it up!
        float vol = Random.Range(volLowRange, volHighRange);
        playerSource.PlayOneShot(coinSound, vol);
        other.gameObject.SetActive(false);// other.gameObject should destroy here by the way.
        getCount = GameObject.FindGameObjectsWithTag("PickUp");
        count = getCount.Length;
        countCollected = countCollected + 1;
        SetCountText();
        if (count < 10)
        {
            // spawns new pick-up objects
            Invoke("SpawnObject", 2.0f);
        }
    }
    if (other.gameObject.tag == "Enemy")
    {
        // if enemy wall... kill the player it is game over
        rend.enabled = false;
        float vol = Random.Range(volLowRange, volHighRange);
        playerSource.PlayOneShot(deathSound, voldeath);
        playerSource.PlayOneShot(explosion, volex);
        yield return new WaitForSeconds (3);
        playerSource.PlayOneShot(gameOver, volgo);
        deathText.text = "GAME OVER!";
        Destroy(Player.gameObject, deathTime);
    }
}

Note: before the addition of yield the code runs perfectly and does everything I want it to.

Thanks for any help you can provide

\$\endgroup\$
1
\$\begingroup\$

You will need to use IEnumerator to be able to use yield. This can be achieved by moving your "death code" into a method and using Coroutines. Make sure you disable the collider to prevent the trigger from executing more than once.

// function to detect whether collision is with a pick-up cube or an emeny wall.
    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("PickUp"))
        {
            // if pick-up object. Pick it up!
            float vol = Random.Range(volLowRange, volHighRange);
            playerSource.PlayOneShot(coinSound, vol);
            other.gameObject.SetActive(false);// other.gameObject should destroy here by the way.
            getCount = GameObject.FindGameObjectsWithTag("PickUp");
            count = getCount.Length;
            countCollected = countCollected + 1;
            SetCountText();
            if (count < 10)
            {
                // spawns new pick-up objects
                Invoke("SpawnObject", 2.0f);
            }
        }
        if (other.gameObject.tag == "Enemy")
        {
            StartCoroutine ("DieRoutine");
        }
    }

    IEnumerator DieRoutine()
    {
        Debug.Log (string.Format ("Die: {0}", "Start"));

        // if enemy wall... kill the player it is game over
        rend.enabled = false;
        float vol = Random.Range(volLowRange, volHighRange);
        playerSource.PlayOneShot(deathSound, voldeath);
        playerSource.PlayOneShot(explosion, volex);
        yield return new WaitForSeconds (3);

        Debug.Log (string.Format ("Die: {0}", "Complete"));

        playerSource.PlayOneShot(gameOver, volgo);
        deathText.text = "GAME OVER!";
        Destroy(Player.gameObject, deathTime);
    }
\$\endgroup\$
  • \$\begingroup\$ This worked Prefectly thanks. I wrote my own Coroutine and IEnumerator but based it off of yours. This was very helpful \$\endgroup\$ – Luke Taylor Dec 14 '15 at 20:59
1
\$\begingroup\$

You already did the trick, use it here once again. To do in that way you have to create your own SoundManager (that is not that big deal, you can do it) and handle everything you required. Well for now you can try

if (other.gameObject.tag == "Enemy")
    {
        // if enemy wall... kill the player it is game over
        rend.enabled = false;
        float vol = Random.Range(volLowRange, volHighRange);
        playerSource.PlayOneShot(deathSound, voldeath);
        playerSource.PlayOneShot(explosion, volex);
        Invoke("GameOver",3.0f);
    }

void GameOver()
{
    playerSource.PlayOneShot(gameOver, volgo);
    deathText.text = "GAME OVER!";
    Destroy(Player.gameObject, deathTime);
}
\$\endgroup\$
0
\$\begingroup\$

If you want wait for thing you can use StartCoroutine.So you need time for waiting , but we haven't time here.right ! you can wait until audiosource.isPlaying equal to true.In below code I try play all sound In same time by for loop but you hear sound when finish before sound because I use StartCoroutine.

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(AudioSource))] //Attach AudioSource component
public class InterferingManager: MonoBehaviour {
    public AudioClip[] audioclips = new AudioClip[5];//audios
    private AudioSource audiosource;// audiosource component

    void Awake()
    {
        audiosource = GetComponent<AudioSource>();
    }
    void Start()
    {
        //when you want test this audiosource's clip shouldn't be null so I put it default sound
        audiosource.clip = audioclips[0];
        audiosource.Play();

        TestDelaying();// call function.I want test Wait until audio is finished
    }


    void TestDelaying () {
        for (int i = 0; i < audioclips.Length; i++)
        {
            StartCoroutine(WaitForSound(audioclips[i]));//pass sounds to `WaitForSound` for Interfering them with each other
        }
    }

    public IEnumerator WaitForSound(AudioClip Sound)
    {
        yield return new WaitWhile(() => audiosource.isPlaying == true); //if audio finished so it should play next audio
        audiosource.clip = Sound;
        audiosource.Play();
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.