-2
\$\begingroup\$

Isn't it possible to start co-routines under certain conditions? Or, it should only be started at the initial steps only?

There is an enemy which will be de-activated after certain condition which works fine. After that, a panel shows up which also works perfectly but in that panel there is a text which will be printed from the above code. When I wrote this exact code in at the start of my game without any condition it worked fine. But now, when I have if statement, it doesn't work.

This code currently prints out the words of my sentences. After typingSpeed seconds, it will print another word and so on. This is a system that we see in our day to day game but I can't seem to get it work the way I want it to.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class LastDIalog : MonoBehaviour {
    public TextMeshProUGUI textDisplay;
    public string[] sentences;
    public int index;
    public GameObject MaxyMory;
    public float typingSpeed;
    // Use this for initialization
    void Start () {
            StartCoroutine (type ());
    }

    // Update is called once per frame
    void Update () {

    }

    IEnumerator type () {
        if (MaxyMory.activeInHierarchy == false) {
            foreach (char letters in sentences[index]) {
                textDisplay.text += letters;
                yield return new WaitForSeconds (typingSpeed);
            }
        }
    }
}

This particular code is not working. Why?

\$\endgroup\$
1
\$\begingroup\$

The if-statement you seem to be writing about is inside the coroutine. At that point the coroutine has already started. The if just decides whether or not the coroutine actually does something.

What you need to do instead is move the if section around the StartCoroutine, so the coroutine is only started under a certain condition. But if you do that in Start, it will only get checked when the game object this script is on is created. If you constantly want to monitor the state of another GameObject and do something when it changes (which seems to be the "MaxyMory" in this case), then you should do so in Update:

void Update () {
    if (MaxyMory.activeInHierarchy == false) {
        StartCoroutine (type ());
    }
}

IEnumerator type () {
        foreach (char letters in sentences[index]) {
            textDisplay.text += letters;
            yield return new WaitForSeconds (typingSpeed);
        }
    }
}

But now you will see a different problem: The coroutine will get started over and over again while the MaxyMory is inactive. You will end up with lots and lots of concurrently running routines. This is likely not what you want. So you need to make sure that the coroutine isn't already running. One way to do that is by adding another private variable isTyping:

private bool isTyping = false;

void Update () {
    if (MaxyMory.activeInHierarchy == false && isTyping == false) {
        isTyping = true;
        StartCoroutine (type ());
    }
}

IEnumerator type () {
        foreach (char letters in sentences[index]) {
            textDisplay.text += letters;
            yield return new WaitForSeconds (typingSpeed);
        }
        isTyping = false;
    }
}

Another solution could be to not trigger the coroutine from an Update script of an unrelated game object, but actually trigger it from the code section which also deactivates the MaxyMory.

\$\endgroup\$
  • \$\begingroup\$ It worked but it only typed a letter. In my case "W". But, it isn't typing other letters, why? \$\endgroup\$ – Yo Ko Hola May 9 at 6:52
  • \$\begingroup\$ @YoKoHola Hard to tell without seeing the full picture. My first guess would be that sentences contains individual letters and not complete strings. Another could be that the value for typingSpeed is too high. \$\endgroup\$ – Philipp May 9 at 9:37
  • 2
    \$\begingroup\$ Myself, when I need to track whether a coroutine is already running, I like to store a Coroutine variable holding the return value of StartCoroutine(), and set it to null when the coroutine finishes. We can compare it to null to check whether it's still running, similar to your bool example, but the advantage is that we can also pass it to StopCoroutine() if we need to interrupt that one specific coroutine instance. \$\endgroup\$ – DMGregory May 9 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.