Empty list and infinite while loop with for loop = crash ?

Hi, Unity freezes on play if the list that needs iterating is empty? I need this same script on multiple objects, but not always the list would be populated with items. To avoid crash I inserted a check that checks for list count before going into the while(true) ?

public List<GameObject> go = new List<GameObject>();

IEnumerator TestRoutine()
    {
        var listCheck = go.Count;
        if (listCheck != 0)
        {
            while (true)
            {
                    for (int i = 0; i < go.Count; i++)
                    {
                        Debug.Log("Name" + go[i].transform.name);
                        yield return null;
                    }

            }
        }
    }

A while(true) will always spin on forever if you never yield. I’m not sure what you’re expecting.

perhaps if you yielded in that while loop level…

There’s no reason that code needs to be a coroutine. Coroutines are meant to be used where you want to split execution across multiple frames or wait for asynchronous tasks. Anything else is just pointless complexity.

public List<GameObject> go = new List<GameObject>();

void Update()
{
    // Whatever

    TestRoutine();
}

void TestRoutine()
{
    var listCheck = go.Count;
    if (listCheck != 0) return;

    for (var i = 0; i < go.Count; i++)
    {
        Debug.Log("Name" + go[i].transform.name);
    }
}

Sorry forgot to include it in the sample code, I have it in the real version, I updated the code sample. Would empty list still break it (It looks like it does, just double checking if I have not made some other mistake)?

Thank you, though I need it as routine, I simplified the sample. Would empty list break the while loop and for iteration (It looks like it does, just double checking if I have not made some other mistake)?

But in that case you either don’t understand what you’re doing or you don’t know what you actually want. Unity scripting for the most part is single threaded and coroutines do not change that. So you literally can imagine your CPU as a guy reading your code, line by line and executing instruction by instruction. A yield means you yield the execution back to the scheduler of the coroutine, i.e. Unity so execution continues and the engine can finish the current frame and some time later the next frame Unity will again “resume” your coroutine where you left off. When your code does not hit any yield statement, what do you think the code should do? An empty while loop that just checks the number of elements in a collection that can never change inside that while loop of course will just keep looping until the end of time because nothing can even possibly change from one iteration to the next. Again the whole CPU thread your program runs on does absolutely nothing except running your loop. That’s it. Btw: That is not a crash. It’s called a hang.

Sounds like you have a misunderstanding of how coroutines work. It’s simulating asychronous behaviour using a system that was intended to be for collections (IEnumerator is the clue). It’s not doing anything special and it’s not running on its own thread (I’m guessing this was your reason for using it).

https://stackoverflow.com/questions/12932306/how-does-startcoroutine-yield-return-pattern-really-work-in-unity

No, the while loop would not terminate in case the list goes empty while the coroutine is running. When that happens the for loop will eventually end and you will be stuck in the while loop without a yield since the for loop would be skipped when the list is empty.

Again, without a yield, your application won’t ever do anything else except running that loop forever. Put a yield inside the while loop and the issue is gone. Each time you hit the yield, your coroutine will be exited and Unity can actually finish the frame.

Yes. The problem is not that the list is empty but the coroutine never reaches yield !

Thank you all for your time

Correct. As others have pointed out above, here is my blurb:

Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

Absolutely NOTHING will happen… until your code either:

  • returns from whatever function it is running

  • yields from whatever coroutine it is running

As long as your code is looping, Unity isn’t going to do even a single frame of change. Nothing.

No exceptions.

“Yield early, yield often, yield like your game depends on it… it does!” - Kurt Dekker

Is it supposed to be more complicated than this? :

public List<GameObject> go = new List<GameObject>();

void PrintNamesInList()
{
    int quantity = go.Count;
    if (quantity == 0) { print("No objects in List 'go'"); return; }
    for (int i = 0; i < quantity; i++)
    {
        print($"index {i} has gameObject {go[i].name}");
    }
}

If so, please explain. :slight_smile:

Yes now when I look at it, feels stupid that I missed it :smile:

Need a coroutine. All good now

I’ve never needed a coroutine.. lol, and if I attempt to make one, I smack myself and realize I’m going about it the wrong way. :face_with_spiral_eyes:

But that’s just me, ignore my hate on coroutines. :slight_smile: