Waiting for a method to signal it is done before launching it again

I am making a visualization in C# where there are a lot of gamemove related ‘actions’. An action can be ‘walk to’, ‘say to’ or ‘pick up’ etc etc. If the story I want to visualize goes like this for example:

  • Player walks to NPC1.
  • Player says to NPC1.

In this case i obviously want the first action (sentence) to be completed before starting the second one. My code looks as follows:

    void Update () {
        parseScenario ();
    }

The definition for the parseScenario function is the following: (small theoretical background (since the implementation is a bit different): entry is a list which contains a number of gamemoves (sentences) to complete. Look at this like a parent list, since each of these lists can contain a number of other gamemoves (sentences) to complete, this is indicated by a _next field which is the next one to do)

  public void parseScenario () {
        foreach (string e in entry) {
            parseEntryLine(e);
        }
    }

The parseEntryLine method looks like this:

public void parseEntryLine (string gm_label) {
        currentGM = findGameMoveByLabel (gm_label);
        if (currentGM.isBrick ()) {
            //Interprete it and perform the animation for it
            animateExpr(currentGM);
  
            //Check if it has a next
            if (currentGM._next != null) {
                parseEntryLine (currentGM._next);
            }
        }
    }

And the animateExpr method is just a function which contains a really big switch statement. Based on what the contents of the ‘action verb’ is, I start a method which performs the action in here.

Now the problem is that obviously when I run it like this the entire story just gets executed immediately.

I cannot figure out how to wait for an action to complete before starting a new one.
Please note that these actions do not have a fixed timespan. (Some require input from the player as well).

I hope the question is clear, if not please ask me to make it more clear.

The simplest way I know is to set a bool while something is happening and then test for it with a coroutine every half second or whatever. Some things, like animations, already have a “isplaying” property, same with sounds, otherwise you need a trigger of some kind.

You should use coroutines.

public IEnumerator parseEntryLine (string gm_label) {
        currentGM = findGameMoveByLabel (gm_label);
        if (currentGM.isBrick ()) {
            //Interprete it and perform the animation for it
            yield StartCoroutine(animateExpr(currentGM));
            //Check if it has a next
            if (currentGM._next != null) {
                parseEntryLine (currentGM._next);
            }
        }
    }

And your animateExpr should be a coroutine which executes the animation and wait until it finishes.

Thank you for your answer Sbizz, I read about coroutines but I did not know if that is what i needed or not! What are the changes required in the animateExpr function to make this work?

It needs to return an IEnumerator, the same way Sbizz has written the parseEntryLine

I don’t know what you’re doing in your function, but something like this:

public IEnumerator myFunction() {
myAnim.play()

    while (myAnim.isPlaying()) {
        yield return null;
    }
}

Kind of pseudo-code; you play your animation and the loop condition checks if the animation is still playing. If it does, you ask to Unity to “come back inside the scope” the next frame (“yield return null”). DO NOT try to loop without a yield statement, you will crash Unity. You can break a coroutine with “yield return break;”.

public IEnumerator myFunction() {
if (myAnim == null) {
    yield return break;
}

myAnim.play()

    while (myAnim.isPlaying()) {
        yield return null;
    }
}

And you can stop a coroutine by stopping the animation :wink:

1 Like

Thanks a lot for your help Sbizz and A. Killingbeck

PS: I did 2 mistakes, it’s not yield return break but yield break and it’s also not yield StartCoroutine(…) but yield return StartCoroutine(…)! :wink: