Search Unity

Bug Coroutine isn't executed

Discussion in 'Scripting' started by magsoftware, Sep 28, 2022.

  1. magsoftware

    magsoftware

    Joined:
    Feb 7, 2019
    Posts:
    123
    Hello,

    The coroutine won't continue executing code after yield return but I don't know why.

    Code example:

    Code (CSharp):
    1. public void ShowFlag()
    2.     {
    3.         StartCoroutine("textupdate");
    4. }
    5.  
    6. IEnumerator textupdate()
    7.     {
    8.         Debug.Log("executed 1");
    9.         yield return new WaitForSecondsRealtime(1.7f);
    10.         Debug.Log("executed 2");
    11.     }
    The "executed 1" is printed in debug console but 'executed 2' is not executed. The code after yield return won't be executed but I don't understand why.

    I tried to change WaitForSecondsRealtime to WaitForSeconds and there is no change.

    Instead, I used 'StartCoroutine("textupdate"); in the void Start method and then the 'executed 2' is now executed.

    What is the problem?


    PS:
    * I didn't change the TimeScale
    * The gameobject isn't destroyed / disabled
    * I didn't use StopAllCoroutines();
     
    Last edited: Sep 28, 2022
  2. TheDevloper

    TheDevloper

    Joined:
    Apr 30, 2019
    Posts:
    69
    your problem here is that you are not calling the ShowFlag function, to do so you should call it on Start or update.
    Start is called once you click play, Update is called every Frame, i will give you another solution which is that you can call ShowFlag from a button.
    Code (CSharp):
    1.     void Start()
    2.     {
    3.         ShowFlag();
    4.     }
    5.     public void ShowFlag()
    6.     {
    7.         StartCoroutine(textupdate());
    8.     }
    9.  
    10.     IEnumerator textupdate()
    11.     {
    12.         Debug.Log("executed 1");
    13.         yield return new WaitForSecondsRealtime(1.7f);
    14.         Debug.Log("executed 2");
    15.     }
     
  3. magsoftware

    magsoftware

    Joined:
    Feb 7, 2019
    Posts:
    123
    I did it, but not inside the code. I am calling ShowFlag using an UI Button :) . The problem isn't solved
     
  4. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    Wow, this post was from the 28th of last month. Surprised it's something still being wrestled with.

    The simple truth is, something is happening that is stopping the coroutine. I know what you listed in your original post, but honestly, when you hit the button for "ShowFlag" if you see the first debug, then it hits your yield and the second doesn't print out, during that time something is happening that either disables the object, the script, stops all coroutines, destroys the object, etc. You'll need to figure out what.

    I usually suggest adding OnDisable and OnDestroy methods to the script so you can add debugs to those and see if they ever print out. This is a good start to see if something is interrupting your script.
     
    Bunny83 and Ryiah like this.
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    Line 8 and 10 are GREAT! Why don't you put something on line 2 as well?

    I bet that NONE of any of the code posted above is even running AT ALL.

    You must find a way to get the information you need in order to reason about what the problem is.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    When in doubt, print it out!(tm)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
    Bunny83 likes this.
  6. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,998
    Well, that's not necessary when the first log inside the coroutine is printing. So we already know he's starting the coroutine, it's just not completing. The reasons are always the same, though we can rule out some thing here. Time.timeScale would not play a role here since he used "WaitForSecondsRealtime". So the only things left over are the other points he listed
    However one point is missing: Disabling the monobehaviour that the coroutine is running on. Even disabling and enabling the monobehaviour in the same frame would stop all coroutines. So it may appear to be still enabled, but the coroutine would still be terminated. I would recommend to add an "OnDisable" callback to that monobehaviour and insert a Debug.Log there to see if and from where the script may be disabled.

    Another rare possibility is that you try to start the coroutine on a prefab instead of a gameobject instance. This does not really work as prefabs do not really "live" in the scene. You can check this by adding a context argument to your Debug.Log calls as second argument. This allows you by clicking on the log message in the console window to highlight / ping that context object in the hierarchy / project view. So use

    Code (CSharp):
    1. Debug.Log("executed 1", this);
     
    Kurt-Dekker likes this.
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,726
    Ha! My eyes passed right over that. Tx Bunny
     
    magsoftware and Bunny83 like this.
  8. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,998
    :) Well "last month" sounds like a long time but it's just over a week now.
     
  9. magsoftware

    magsoftware

    Joined:
    Feb 7, 2019
    Posts:
    123
    Thanks guys, I didn't find the solution, so I changed the parent object of the script outside the canvas and it works now.