Are co routines conflicting with each other somehow in this code?

Hi, I’m trying to get my hint system to work properly and I’m not sure if I’m doing the right thing.

It should work like this:

  1. The function that shows a hint is being called from another script;

  2. Text has to fade in and out (alpha) when a hint is being shown;

  3. If a hind is currently being shown, we have to queue the incoming hint and waint for the current one to end and only then show the incoming hint;

This code worked until I added text fade in/out:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

class Hint
{
    public Hint(string msg, float scnd)
    {
        message = msg;
        seconds = scnd;
    }

    public string message;
    public float seconds; // duration
}

public class HintTextScript : MonoBehaviour {

    public Text hintText;

    private bool isHintShowing;

    private Stack<Hint> queuedHints;

    // Use this for initialization
    void Start () {
        queuedHints = new Stack<Hint>();

        hintText.text = "";
        isHintShowing = false;
    }

    // Update is called once per frame
    void Update()
    {
        if (!isHintShowing && queuedHints.Count > 0) // we have some hint waiting to be shown...
        {
            Debug.Log("Showing hint!");

            StartCoroutine(changeTextFor(queuedHints.Peek().message, queuedHints.Peek().seconds));
            queuedHints.Pop();
        }
    }

    public void ShowHintFor(string Message, float Seconds)
    {
        if (isHintShowing)
        {
            // if some hint is currently being shown, let's queue our passed hint
            Debug.Log("Queueing in a hint");

            queuedHints.Push(new Hint(Message, Seconds));
            return;
        }

        Debug.Log("Showing hint!");
        StartCoroutine(changeTextFor(Message, Seconds));
    }

    IEnumerator changeTextFor(string Message, float Seconds)
    {
        isHintShowing = true;

        hintText.text = Message;

        // breaks the code
        //StartCoroutine(FadeTextToFullAlpha(1f, hintText));

        yield return new WaitForSeconds(Seconds);

        // breaks the code
        //StartCoroutine(FadeTextToZeroAlpha(1f, hintText));

        hintText.text = "";
        hintText.color = new Color(hintText.color.r, hintText.color.g, hintText.color.b, 1.0f);

        Debug.Log("Alpha of hint text: " + hintText.color.a);
        isHintShowing = false;
    }
    
    IEnumerator FadeTextToFullAlpha(float t, Text i)
    {
        i.color = new Color(i.color.r, i.color.g, i.color.b, 0);
        while (i.color.a < 1.0f)
        {
            i.color = new Color(i.color.r, i.color.g, i.color.b, i.color.a + (Time.deltaTime / t));
            yield return null;
        }
    }

    IEnumerator FadeTextToZeroAlpha(float t, Text i)
    {
        i.color = new Color(i.color.r, i.color.g, i.color.b, 1);
        while (i.color.a > 0.0f)
        {
            i.color = new Color(i.color.r, i.color.g, i.color.b, i.color.a - (Time.deltaTime / t));
            yield return null;
        }
    }
}

Are co routines in this code somehow conflicting with each other is it something else that’s causing trouble? Please help.

Look, you seem to have a problem. You posted a question, most likely to solve that problem. However you haven’t even mentioned your problem. All you have written is // breaks the code whatever that means. Does your PC crash? Does the game crash? If it just doesn’t do what you expecting, what does it do instead? Any observations?

The only thing that could cause trouble here is that you do not wait for your fading coroutines to finish. In other words

Those two lines:

StartCoroutine(FadeTextToFullAlpha(1f, hintText));
yield return new WaitForSeconds(Seconds);

would do two things: It starts the “FadeIn” coroutine and it will pause the “changeTextFor” coroutine for “Seconds” seconds.

When those seconds have passed you execute those four lines:

     StartCoroutine(FadeTextToZeroAlpha(1f, hintText));
     hintText.text = "";
     hintText.color = new Color(hintText.color.r, hintText.color.g, hintText.color.b, 1.0f);
     isHintShowing = false;

Note that the last three lines are immediately called after your “fade out” coroutine has started. You may wanted to yield for those coroutines. Like:

     yield return StartCoroutine(FadeTextToFullAlpha(1f, hintText));
     yield return new WaitForSeconds(Seconds);
     yield return StartCoroutine(FadeTextToZeroAlpha(1f, hintText));

This will first wait until the FadeTextToFullAlpha coroutine has finished and then wait for the specified amount of seconds. When that time has passed it will fade out and wait until it has been faded out completely before running the last bit of your “changeTextFor” coroutine.

If you have any other issues, you should include a description of those issues in your question.

ps: It would be way easier to do the fading directly inside the changeTextFor coroutine

Color c = hintText.color;
while (c.a < 1.0f)
{
    c.a += Time.deltaTime / fadeInSpeed;
    hintText.color = c;
    yield return null;
}
yield return new WaitForSeconds(Seconds);
while (c.a > 0f)
{
    c.a -= Time.deltaTime / fadeOutSpeed;
    hintText.color = c;
    yield return null;
}