Search Unity

Question How to pause and resume Coroutine

Discussion in 'Scripting' started by Only4gamers, Jan 15, 2021.

  1. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    Hello everyone,
    In my endless racer game there is continuously points adding while game in progress. After 20 seconds point starting to multiply by 2, then after 50 seconds multiply by 3, then after 90 seconds multiply by 4 and later by 5. And Points should only add while game in progress. I have script ready for everything but I don't know how to pause this coroutine while game is not in progress and resume later when game resumes. Here is current script:

    Code (CSharp):
    1. IEnumerator PointMultiplier()
    2.         {
    3.             while(true)
    4.             {
    5.                 yield return new WaitForSeconds(0.1f);
    6.                 if(GameManager.Instance.Status == GameStatus.GameInProgress)
    7.                 {
    8.                     yield return new WaitUntil(() => LevelManager.gameStarted);
    9.                     yield return new WaitForSeconds(20f);
    10.                     pointMultipier = 2;
    11.                     multiplier.text = "X" + pointMultipier.ToString();
    12.                     multiplier.GetComponent<Animation>().Play();
    13.  
    14.                     // StartCoroutine(MultiplierLerp());
    15.                     yield return new WaitForSeconds(50f);
    16.                     pointMultipier = 3;
    17.                     multiplier.text = "X" + pointMultipier.ToString();
    18.                     multiplier.GetComponent<Animation>().Play();
    19.  
    20.                     yield return new WaitForSeconds(90f);
    21.                     pointMultipier = 4;
    22.                     multiplier.text = "X" + pointMultipier.ToString();
    23.                     multiplier.GetComponent<Animation>().Play();
    24.  
    25.                     yield return new WaitForSeconds(130f);
    26.                     pointMultipier = 5;
    27.                     multiplier.text = "X" + pointMultipier.ToString();
    28.                     multiplier.GetComponent<Animation>().Play();
    29.                 }
    30.             }
    31.         }
    Can someone please modify and complete my script?
    Thanks.
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    The simplest way would be to use Time.timeScale to pause the game(set it to 0). Your code here will work without any modifications if you do that.
     
    tomwilswood and Only4gamers like this.
  3. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    Thanks but it's not just about pause. I am already using Time.timeScale while pause. Game character have 3 lives. When it die once game still running and on first tap character respawn. So between character death and respawn this coroutine should pause.
     
  4. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    I have this line to check wheter game is in progress or not. But how to use this to pause and resume coroutine? any idea?
    Code (CSharp):
    1. if(GameManager.Instance.Status == GameStatus.GameInProgress)
     
  5. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    Of you want more fine-grained control than what you can get with timescale, you'll need to keep your own timer variable instead of depending on WaitForSeconds.
     
    Only4gamers likes this.
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,689
    Yes! This is already built in for you with this handy API:

    https://docs.unity3d.com/ScriptReference/WaitUntil.html

    So in your coroutine, to wait until the game is in progress:

    Code (csharp):
    1. yield return new WaitUntil( () => {
    2.     return GameManager.Instance.Status == GameStatus.GameInProgress;
    3. } );
    The above code will keep yielding until that delegate returns
    true
    .
     
  7. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    Only problem with this is you can't do it during one of the
    yield return new WaitForSeconds()
    to extend said wait...
     
    Only4gamers likes this.
  8. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,689
    True... but you could implement your own that waits until either or both conditions are true.

    OP, if you make a separate little coroutine that loops until a timer counts up to your wait time, AND the condition is true, you can yield return that coroutine and things won't move forward until both of those conditions are true.

    Or you could just wait the time, THEN wait the condition, unless you intend the condition should shortcut the time.
     
    Only4gamers likes this.
  9. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,909
    Right, so ultimately, you'd be implementing your own counter, assuming you want the condition to pause the timer.
     
    Only4gamers likes this.
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,689
    Hahaha, software specification is hard. Does the condition being false extend the timer? Or merely prevent its normal expiration?

    IOW, does the time only advance when the condition is true, or does the time advance blindly, THEN start checking the condition.

    Software is the final frontier.
     
    Only4gamers and PraetorBlue like this.
  11. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    Ok, I succeed to complete this code:
    Code (CSharp):
    1. void Update()
    2.         {
    3.             if(GameManager.Instance.Status == GameStatus.GameInProgress)
    4.             {
    5.                 timer += Time.deltaTime;
    6.                 // Debug.Log(timer);
    7.             }
    8.         }
    9.  
    10.         int pointMultipier = 1;
    11.         public Text multiplier;
    12.         int i = 0;
    13.         IEnumerator PointMultiplier()
    14.         {
    15.             while(true)
    16.             {
    17.                 yield return new WaitForSeconds(1f);
    18.    
    19.                 if(timer > 290 && i == 3)
    20.                     {
    21.                         pointMultipier = 5;
    22.                         multiplier.text = "X5";
    23.                         multiplier.GetComponent<Animation>().Play();
    24.                         break;
    25.                     }
    26.  
    27.                 else if(timer > 160 && i == 2)
    28.                     {
    29.                         pointMultipier = 4;
    30.                         multiplier.text = "X4";
    31.                         multiplier.GetComponent<Animation>().Play();
    32.                         i++;
    33.                     }
    34.  
    35.                 else if(timer > 70 && i == 1)
    36.                     {
    37.                         pointMultipier = 3;
    38.                         multiplier.text = "X3";
    39.                         multiplier.GetComponent<Animation>().Play();
    40.                         i++;
    41.                     }
    42.  
    43.                 else if(timer > 20 && i == 0)
    44.                     {
    45.                         pointMultipier = 2;
    46.                         multiplier.text = "X2";
    47.                         multiplier.GetComponent<Animation>().Play();
    48.                         i++;
    49.                     }
    50.             }
    51.         }
    Maybe it will help someone.