Unity Coroutines, some lines executed repeatedly when not inside a loop?

So I am building a traffic system for my game and came into this problem.

Take a look at this coroutine.

 private IEnumerator InvertTrafficLights2()
        {
            var greenTrafficLights = GameObject.FindObjectsOfType<TrafficLight>().Where(x => x.CurrentColor == Color.green);
            var redTrafficLights = GameObject.FindObjectsOfType<TrafficLight>().Where(x => x.CurrentColor == Color.red);

            Debug.Log("greenTrafficLights.Count() = " + greenTrafficLights.Count());
            Debug.Log("redTrafficLights.Count() = " + redTrafficLights.Count());

            yield return StartCoroutine(greenTrafficLights.ElementAt(0).Invert());

            Debug.Log("redTrafficLights.Count() = " + redTrafficLights.Count());

            yield return null;
        }

And this is the TrafficLight.Invert coroutine:

public Color CurrentColor;

        public IEnumerator Invert()
        {
            if (CurrentColor == Color.red)
                CurrentColor = Color.green;
            else
            {
                CurrentColor = Color.red;
            }

            GetComponent<MeshRenderer>().material.color = CurrentColor;

            yield return null;
        }

Pretty simple, you call invert and the traffic light inverts its color.

By the way, the reason I am using a Coroutine for the Invert method is that I will use an yellow light in between the green and red switch, so I gotta switch to yellow, wait a couple seconds and switch to red, makes the code more readable instead of using Update()

This example is just simpler.

But anyways, the problem is that when I take a look at the log I see this:

And when using Visual Studio to step through the code, I see that this breakpoint is hit 2 times:

Its like the coroutine is populating my IEnumerable 2 times, one before I switch the traffic light to red, and one after that happens, thats why It says red = 1. And that should not happen as the traffic light only changes it color after that IEnumerable call

Why does that happen? I thought coroutines worked differently than that, For example, Debug.Log() calls do not get repeated.

Your console log looks fine to me. I see three log statements in the code and three log statements in the console.

Anyway, how are you starting the invertTrafficLights2 coroutine? The simplest explanation for what you’re seeing in the debugger is that you have started that coroutine twice.

If the coroutine was started twice i should see 6 logs in the console, not 3.

The logs are fine, what is not is the values shown in them, take a second look, the third log should still show 0.

EDIT:

HMMM funny! if i add a .ToList() at the end of my calls it works?

6187842--678351--upload_2020-8-10_11-37-1.png

6187842--678354--upload_2020-8-10_11-37-41.png

This must be something in the IEnumerable interface that I am not aware of.

Oh sorry I’m still half asleep - the reason the breakpoint gets hit multiple times is probably because it’s breaking inside the Where clause lambda. When you add ToList() that forces LINQ to unravel your IEnumerator into an actual collection which won’t change.

1 Like

No problem friend, thanks for the clarification! It makes sense.