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. Dismiss Notice

Resolved Can‘t stop coroutine with yield return [iterator block]?

Discussion in 'Scripting' started by kuailemario, Nov 25, 2020.

  1. kuailemario

    kuailemario

    Joined:
    Mar 19, 2020
    Posts:
    23
    I made a coroutine similar to recursion. When recursive only once, everything works fine.
    After more than two times, the coroutine can no longer be stopped.
    If I use the enumerator reference (see [SOLUTION] comment), there is no problem.
    Ask everybody, why?

    EDIT: [SOLUTION] is not good, cause other bugs.
    You can reproduce it in Unity 2018.3.10 and 2018.4.29, but Unity 2019 is different.

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4. public class CorTest : MonoBehaviour
    5. {
    6.     private int count = 2;
    7.     private bool flag = false;
    8.     private Coroutine cor;
    9.     private IEnumerator corum;
    10.     IEnumerator CorA()
    11.     {
    12.         yield return new WaitUntil(IsFlag);
    13.         if(count > 0)
    14.         {
    15.             print("Coroutine is running,we need:" + count);
    16.             count--;
    17.             flag = false;
    18.             yield return CorA();
    19.             // yield return corum;      // [SOLUTION]
    20.         }
    21.         else
    22.         {
    23.             print("Coroutine is running,count <= 0");
    24.         }
    25.     }
    26.     bool IsFlag()
    27.     {
    28.         return flag;
    29.     }
    30.  
    31.     // [↑ ↓ →]      Coroutine Can Stop.
    32.     // [↑ ↓ ↓ →]    Coroutine Can't Stop Now.
    33.     // [↑ ↓ ↓ ←]    Coroutine Can Stop.
    34.     private void Update()
    35.     {
    36.         if (Input.GetKeyDown(KeyCode.LeftArrow))
    37.         {
    38.             print("StopAllCoroutines");
    39.             StopAllCoroutines();
    40.             flag = true;
    41.         }
    42.         else if (Input.GetKeyDown(KeyCode.RightArrow))
    43.         {
    44.             print("StopCoroutine");
    45.             StopCoroutine(cor);
    46.             // StopCoroutine(corum);    // [SOLUTION]
    47.             flag = true;
    48.         }
    49.         else if (Input.GetKeyDown(KeyCode.UpArrow))
    50.         {
    51.             print("StartCoroutine");
    52.             flag = false;
    53.             count = 2;
    54.             cor = StartCoroutine(CorA());
    55.             corum = CorA();
    56.         }
    57.         else if (Input.GetKeyDown(KeyCode.DownArrow))
    58.         {
    59.             print("Make flag TRUE");
    60.             flag = true;
    61.         }
    62.     }
    63. }
     
    Last edited: Nov 27, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,336
    If all you are doing is a task for
    count
    steps, do you really need recursion?
     
    Bunny83 and PraetorBlue like this.
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,697
    What exactly is your goal here? Whatever you're trying to do, this seems like a really confusing and convoluted way to do it.
     
    Bunny83 likes this.
  4. kuailemario

    kuailemario

    Joined:
    Mar 19, 2020
    Posts:
    23
    I am making a video player function and need to play a segment of the video in loop
    count
    , so I made a wait.
    As you said, it is indeed possible to solve this problem with a simple
    for
    !
    I'm just curious, why this way of writing
    CorA()
    causes the coroutine to fail to stop after recursive twice.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,336
    Let us know what you find out!
     
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,446
    I saw this question yesterday but didn't answer yet. However I highly doubt that your code wouldn't work. I quickly copied your script into my test project which is using Unity 2019.2.14f1. I replaced your keys with GUI buttons as it's easier to follow what you're doing ^^. I had no issues stopping the coroutine at any stage.

    I even increased the count to 5 and pressed the "flag" button 4 times. I stopped the coroutine and pressed the flag button again and nothing happens as expected. So the coroutine has been stopped.

    You said:
    How do you know that the coroutine isn't stopped? Once I stop the coroutine I don't get any log from the coroutine anymore.

    Keep in mind when you start a new coroutine while you still have a coroutine running, you will loose the reference to your coroutine as you would overwrite your "cor" variable. That coroutine will of course continue to run and you don't have a way to stop it besides StopAllCoroutines. As far as I can tell, everything works as it should. So you should be more specific what exactly doesn't work and how you can tell it doesn't work.
     
    kuailemario likes this.
  7. kuailemario

    kuailemario

    Joined:
    Mar 19, 2020
    Posts:
    23
    Thank you very much for your answers.

    I was shocked when I saw this. I did see log printing after stopping the coroutine.

    I'm sorry I didn't provide more detailed information, the Unity version I am using is 2018.3.10.
    So I think this is probably an issue with the old version.

    I immediately used Unity 2018.4.29 to test it, and I can get the log.


    Then I moved to Unity 2019.3.8, and the coroutine stopped correctly.


    Wow! I should think that the coroutine method is on Monobehavior and may be updated.

    The packaging of Unity and C# always makes it difficult to get into the details, I can only guess what happened. Thanks again.
     
    Last edited: Nov 27, 2020