Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Delaying button actions with Coroutines

Discussion in '2D' started by YoYoYoYo_111_PiPi, Oct 2, 2016.

  1. YoYoYoYo_111_PiPi

    YoYoYoYo_111_PiPi

    Joined:
    Jun 23, 2016
    Posts:
    80
    Hi, I was wondering how can I delay button actions with Coroutines. Specifically the application's end, and scene transitions. So, I have a button in my menu that once you press it, it exits the application. Also, I have buttons that lead me to another scenes/menus. The reason why I want to delay the actions is because of the sound, especially while exiting. It doesn't wait one bit, and I would like for it to wait for about 2-3 seconds (sound length).

    So here's my code for scene transitions:

    "using UnityEngine;
    using System.Collections;
    using UnityEngine.SceneManagement;

    public class Menu : MonoBehaviour
    {

    public void LoadScene(string sceneName)
    {
    SceneManager.LoadScene(sceneName);
    }

    }"

    And here is for the exit:

    "using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;

    public class Exit : MonoBehaviour {

    public void Quit()
    {

    Application.Quit();

    }

    }"

    They're both attached to the object that is later added to the specific button. So, can I add an IEnumarator to these scripts each, or do I need to create a new, separate script? I'm new with scripting, so I can't seem to get it to work on my own properly. If someone knows what exactly to write for these examples, I would be more than thankful.
     
  2. SullyTheStrange

    SullyTheStrange

    Joined:
    May 17, 2013
    Posts:
    147
    So basically what you wanna do is have a simple coroutine like this:
    Code (CSharp):
    1. // Pass in the string sceneName so you can use it in here
    2. IEnumerator LoadSceneDelayed(string sceneName)
    3. {
    4.      loading = true; // A new variable to let the button know that the loading has started, so don't start the coroutine a second time
    5.      yield return new WaitForSeconds(2); // This statement will make the coroutine wait for the number of seconds you put there, 2 seconds in this case
    6.      SceneManager.LoadScene(sceneName);
    7. }
    That coroutine will wait the number of seconds you specify, and then load the given scene. So in your LoadScene function, you would call the coroutine like this:

    Code (CSharp):
    1. bool loading = false; // A new variable which is set to true when the coroutine is called, to prevent it from being called more than once
    2.  
    3. public void LoadScene(string sceneName)
    4. {
    5. if (!loading) // Only start the coroutine if loading is false, meaning it hasn't already been started
    6.      StartCoroutine(LoadSceneDelay(sceneName));
    7. }
    And that's that!

    I took the liberty of adding a new variable called "loading". This keeps anything from messing up if the player clicks the button repeatedly, so the coroutine will only be called once.

    The same setup will work for what you want to do with quitting, too. Let me know if you have any more questions! Coroutines are a little weird at first but once you know how they work, they're VERY useful for scripting. :D
     
  3. YoYoYoYo_111_PiPi

    YoYoYoYo_111_PiPi

    Joined:
    Jun 23, 2016
    Posts:
    80
    Thank you very much, I'll test it out, and tell you if there are any problems.
     
  4. YoYoYoYo_111_PiPi

    YoYoYoYo_111_PiPi

    Joined:
    Jun 23, 2016
    Posts:
    80
    Yup, having problem writing it. I don't know exactly where to place it within my code... if it's not too much of a hassle to write the whole thing the way it should be, I would appreciate it very much. Sorry for being a dummy :(.
     
  5. SullyTheStrange

    SullyTheStrange

    Joined:
    May 17, 2013
    Posts:
    147
    No worries, man. :) The original functions you had at the start, those were already working, right? All you have to do is put the coroutine in the same script as the corresponding function, and it should work fine. As long as it's in the same script, it'll know what you're talking about when you use the coroutine's name.

    So the whole Menu script should look like this:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public class Menu : MonoBehaviour
    6. {
    7.  
    8. bool loading = false; // A new variable which is set to true when the coroutine is called, to prevent it from being called more than once
    9.  
    10. public void LoadScene(string sceneName)
    11. {
    12. if (!loading) // Only start the coroutine if loading is false, meaning it hasn't already been started
    13.      StartCoroutine(LoadSceneDelay(sceneName));
    14. }
    15.  
    16. // Pass in the string sceneName so you can use it in here
    17. IEnumerator LoadSceneDelayed(string sceneName)
    18. {
    19.      loading = true; // A new variable to let the button know that the loading has started, so don't start the coroutine a second time
    20.      yield return new WaitForSeconds(2); // This statement will make the coroutine wait for the number of seconds you put there, 2 seconds in this case
    21.      SceneManager.LoadScene(sceneName);
    22. }
    23.  
    24. }
    And again, the other script Exit can be written the same way.
     
  6. YoYoYoYo_111_PiPi

    YoYoYoYo_111_PiPi

    Joined:
    Jun 23, 2016
    Posts:
    80
    It works now, thank you very much. You're a big help