Get a "Another coroutine is already waiting for" log... Why?

Hi everybody!

We are currently working on some basic architecture process and we try to use coroutine to avoid too heavy loading lag.
We have had no problem with them until now and we use them in single coroutine or chained ones without any problem.

But we just got a “log” (not an error, nor a warning, just a log) which said that “Another coroutine is already waiting for this coroutine!”…

This came out when we try to start a new coroutine without linked it to the “main” coroutine.

I will use an example as it will be really easier to explain…

Let’s say you have a first object “ViewManager” which must load all the view and gui stuff. Another object called “View” which is responsible to load the 3d scene and choose a “GuiScreen” to display. And finally the “GuiScreen” which describe the button position, the button behavior, etc.

Mainly, what we do is :

void ViewManager.Show(string viewName)
{
  View view = GetView(viewName)
  this.StartCoroutine(this.ShowAsync(view));
}

IEnumerator ViewManager.ShowAsync(View view)
{
  yield return this.StartCoroutine(view.Activate(true));
  yield return this.StartCoroutine(view.Focus(true));
}

IEnumerator View.Focus(bool focused)
{
  if (focused)
  {
    GuiScreen screen = Gui.GetScreen("ScreenName");
    screen.Show();
  }
}

void GuiScreen.Show()
{
  if (!this.IsVisible)
  {
    if (this.Showing == null)
    {
      // Print a log!!!!
      this.Showing = this.StartCoroutine(this.ShowAsync());
    }
  }
}

It’s like if Unity is able to say :
“Hey, we have a first coroutine “FocusAsync”, then some non-coroutine call, so no yield, nor IEnumerator and finally a new call to “StartCoroutine(ShowAsync())”. But you cannot do that unless you link the ShowAsync to FocusAsync with IEnumerable all the way along”.

But, we don’t care to wait on the “ShowAsync” to finish the “FocusAsync” one… so what’s wrong with this?
Has anybody get the same behavior? Did you find a workaround? or do we made something wrong?

Thanks for reading and I hope someone will have any insights!!!

Cheers!

As suggested in the comment, here is the answer at my question.
Zerot write it down clearly:

I haven’t tested it, but i’m guessing that this message shows up if you store the result of StartCoroutine and try to yield on it from 2 different coroutines.

Let’s say you have a class which need to be “Initialized”, then “Loaded” and finally “Shown”.
What we do is use a coroutine for each state and wait that the previous one is ended before doing the current state actions.
You can do that by looping until the “previsous state is finished” and yield or just say “ok I will let the other state more time to run by calling the coroutine in the current state coroutine”… and that’s the wrong option ^^

Here is a example of code:

class Test
{
  private Coroutine initializing;
  private Coroutine loading;
  private Coroutine showing;

  public void Initialize()
  {
    if (this.initializing == null)
    {  
      this.initlializing = this.StartCoroutine(this.InitializeAsync());
    }
  }

  public void Load()
  {
    if (this.loading== null)
    {  
      this.loading = this.StartCoroutine(this.LoadAsync());
    }
  }

  public void Load()
  {
    if (this.showing == null && !IsVisible)
    {  
      this.showing = this.StartCoroutine(this.ShowAsync());
    }
  }

  private IEnumerator InitializeAsync()
  {
     // Do some stuff here...
     yield return null;
     yield return null;

     this.initializing = null;
     this.Initialized = true;
  }

  private IEnumerator LoadAsync()
  {
     **// The correct way to wait on another coroutine to finish...**
     while(this.initializing != null)
     {
       yield return null;
     }

     // Do loading stuff here.

     this.loading = null;
     this.Loaded = true;
  }

  private IEnumerator ShowAsync()
  {
     **// The wrong way to wait on another coroutine to finish...**
     if(this.loading != null)
     {
        yield return this.loading;
     }

     // Do showing stuff here.

     this.showing = null;
     this.IsVisible = true;
  }
}

I hope the answer is clear enough to be understand…

Cheers!