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 Coroutine wait until a condition?

Discussion in 'Scripting' started by Proxima_Centauri, Nov 3, 2020.

  1. Proxima_Centauri

    Proxima_Centauri

    Joined:
    Oct 20, 2020
    Posts:
    42
    I'm making a Cutscene in a Coroutine, so I want to do something and then make the game wait until a continueCutscene bool is true, so it goes on with the cutscene, something like this

    Code (CSharp):
    1. IEnumerator Cutscene()
    2.     {
    3.         //Cutscene Stuff
    4.         continueCutscene = false;
    5.         yield return new WaitUntil(continueCutscene == true);
    6.         //More Cutscene Stuff and End the cutscene
    7.     }
    However, I don't know how to do the syntax yield return new WaitUntil(continueCutscene == true); so the program actually waits for a condition to become true, how do I do that?
     
  2. Vryken

    Vryken

    Joined:
    Jan 23, 2018
    Posts:
    2,106
    You need to pass in a delegate function into
    WaitUntil
    ; the condition to wait for needs to be outside of the coroutine.
    For example:
    Code (CSharp):
    1. public class Example : MonoBehaviour {
    2.    IEnumerator StartTask() {
    3.       Debug.Log("Start");
    4.  
    5.       yield return new WaitUntil(SomeLongAsyncTaskOrWhatever);
    6.  
    7.       Debug.Log("Finish");
    8.    }
    9.  
    10.    //Returns false while the task is still running, and true when it's finished.
    11.    bool SomeLongAsyncTaskOrWhatever() {
    12.       //etc..
    13.    }
    14. }
    With the way you're trying to structure your setup though, you can probably do something like this instead...
    Code (CSharp):
    1. public class Example : MonoBehaviour {
    2.    bool isCutscenePlaying;
    3.  
    4.    void StartCutscene() {
    5.       isCutscenePlaying = true;
    6.       StartCoroutine(Cutscene());
    7.    }
    8.  
    9.    IEnumerator Cutscene() {
    10.       while(isCutscenePlaying) {
    11.          //Cutscene stuff.
    12.       }
    13.    }
    14. }
    ...And then just set
    isCutscenePlaying
    back to false whenever the cutscene finishes.
     
  3. Proxima_Centauri

    Proxima_Centauri

    Joined:
    Oct 20, 2020
    Posts:
    42
    I tried bringing my bool out of the Coroutine, but it doesn't work. It tells me that I can't convert from 'bool' to a System.Func<bool>. This is the code


    Code (CSharp):
    1. //Start Cutscene
    2. continueCutscene = false;
    3.                     StartCoroutine(Cutscene());
    4.  
    5. IEnumerator Cutscene()
    6.     {
    7.         //Cutscene
    8.         yield return new WaitUntil(continueCutscene);
    9.         //Cutscene
    10.     }
     
  4. raarc

    raarc

    Joined:
    Jun 15, 2020
    Posts:
    535
    easier to do it like this

    Code (CSharp):
    1.     IEnumerator Cutscene()
    2.         {
    3.             //Cutscene Stuff
    4.             continueCutscene = false;
    5.  
    6. while(continueCutscene == false)  {
    7.             yield return null;
    8. }
    9.             //More Cutscene Stuff and End the cutscene
    10.         }
    11.  
     
    furkan83 likes this.
  5. Proxima_Centauri

    Proxima_Centauri

    Joined:
    Oct 20, 2020
    Posts:
    42
    Yes, that code worked! I just changed the if to summarize it as if (!continueCutscene), thank you very much!!
     
    unity_JRZnapB6Q3lRmw and raarc like this.
  6. Krishx007

    Krishx007

    Joined:
    Jul 15, 2014
    Posts:
    14
    Code (CSharp):
    1. //Useful when we want to hold a IEnumerator method which is using for/while loop until the passed "checkMethod" returns true
    2. //It is needed coz in IEnumerator method we cant pass boolean variable by reference
    3.  
    4.  
    5. using System.Collections;
    6. using System.Collections.Generic;
    7. using UnityEngine;
    8. using kFramework;
    9. public class CoroutineLoopTest : MonoBehaviour
    10. {
    11.     // Start is called before the first frame update
    12.     void Start()
    13.     {
    14.         StartCoroutine(WrongWayToPauseLoop());
    15.         StartCoroutine(CorrectWayToPauseLoop());
    16.     }
    17.     // Update is called once per frame
    18.     IEnumerator WrongWayToPauseLoop()
    19.     {
    20.         print("Start");
    21.         int index = 0;
    22.         while (index <= 20)
    23.         {
    24.             //This will not stop while loop or for loop
    25.             yield return null;
    26.             print("WrongWay Index= " + index);
    27.             index++;
    28.         }
    29.         print("End");
    30.     }
    31.     IEnumerator CorrectWayToPauseLoop()
    32.     {
    33.         print("Start");
    34.         int index = 0;
    35.         while (index <= 20)
    36.         {
    37.             //Hold the coroutine loop until space button is clicked
    38.             yield return WaitUntilTrue(IsSpaceKeyPressed);
    39.             print("CorrectWay Index= " + index);
    40.             index++;
    41.         }
    42.         print("End");
    43.     }
    44.     bool IsSpaceKeyPressed()
    45.     {
    46.         return Input.GetKeyDown(KeyCode.Space);
    47.     }
    48.  
    49.        public IEnumerator WaitUntilTrue(Func<bool> checkMethod)
    50.         {
    51.             while (checkMethod() == false)
    52.             {
    53.                 yield return null;
    54.             }
    55.         }
    56.  
    57.  
    58. }
     
  7. Delphoenyx

    Delphoenyx

    Joined:
    Jun 20, 2021
    Posts:
    4
    You are passing just a bool variable as a parameter to WaitUntil. That doesn't work like that.
    I had the same error and I solved it like the following.

    1. You may leave your code as is. Your continueCutscene variable it's okay.
    2. Add the following line.
    Code (CSharp):
    1. private bool CanContinueCutScene() => continueCutscene;
    3. Or alternativelly, add the following function, which it's equivalent.
    Code (CSharp):
    1. private bool CanContinueCutScene(){
    2.     return continueCutscene;
    3. }
    4. Change your line
    yield return new WaitUntil(continueCutscene);
    to the following:
    Code (CSharp):
    1. yield return new WaitUntil(CanContinueCutscene);
    That way, you are using your function as a way to "check" whether or not some condition has met.

    The variable thing doesn't work because is just something that stores a value.WaitUntil requieres something that can check the value of something, thus a function.
     
    adityaBLI and infabong like this.
  8. infabong

    infabong

    Joined:
    Feb 4, 2022
    Posts:
    3
    Very solid explaination, fitted to my brain. Thank you
     
  9. mattseaton22

    mattseaton22

    Joined:
    Sep 12, 2019
    Posts:
    43
    Yes you need a delegate, a Func<bool>, not a bool.

    I'm surprised no one has mentioned lambda functions. It's much more concise.

    Code (CSharp):
    1. // Change this
    2. yield return new WaitUntil(continueCutscene == true);
    3.  
    4. // to this
    5. yield return new WaitUntil(() => continueCutscene);
    There's no point in ever putting someBool == true. They always evaluate to the same thing.
     
    SergeiKazantsev likes this.