Unity C#:启动新协程前等待前一个协程完成
Hey there! Let's work through your Unity coroutine problem since you're still getting familiar with how they work.
First, let's break down why your current approaches aren't working:
Parallel coroutine race condition
When you callStartCoroutine(Coroutine1)andStartCoroutine(Coroutine2)back-to-back, both coroutines run at the same time. That meansCoroutine2might try to access the lists beforeCoroutine1finishes generating both—hence the error when only one list exists.Nested coroutine lockup
PuttingCoroutine2insideCoroutine1's loop causes a freeze because ifCoroutine2doesn't have anyyield returnstatements to pause and let the main thread breathe, it'll block execution entirely. Even if it does, running it in a tight loop without proper yielding will starve Unity's main loop.
Here are two solid solutions tailored to your goal of avoiding lag while ensuring data is ready:
Solution 1: Wait for both lists to generate before running Coroutine2
This is the simplest fix if you need both lists fully ready before processing. Split your list generation into smaller, yield-friendly chunks to prevent lag, then start Coroutine2 only after both are done:
// Your two lists (make sure they're initialized somewhere!) private List<YourDataType> list1 = new List<YourDataType>(); private List<YourDataType> list2 = new List<YourDataType>(); void Test() { // Just start the main coordinator coroutine StartCoroutine(CoordinateListGenerationAndProcessing()); } IEnumerator CoordinateListGenerationAndProcessing() { // Generate first list in chunks to avoid lag yield return GenerateList(list1, 1000); // Pass list and total items to generate // Generate second list similarly yield return GenerateList(list2, 1000); // Now both lists are ready—start processing yield return StartCoroutine(Coroutine2()); } IEnumerator GenerateList(List<YourDataType> targetList, int totalItems) { for (int i = 0; i < totalItems; i++) { // Add your item generation logic here targetList.Add(CreateYourDataItem()); // Yield every 100 items to let Unity process input/rendering if (i % 100 == 0) yield return null; } } IEnumerator Coroutine2() { // Process both lists here—also add yields if processing is heavy! foreach (var item in list1) { ProcessItem(item); if (list1.IndexOf(item) % 50 == 0) yield return null; } foreach (var item in list2) { ProcessItem(item); if (list2.IndexOf(item) % 50 == 0) yield return null; } }
Solution 2: Process each list as soon as it's generated
If you don't need both lists ready at the same time, you can start processing the first list immediately after it's done generating, while the second list is still being built. This keeps things running in parallel without blocking:
void Test() { StartCoroutine(CoordinateParallelGenerationAndProcessing()); } IEnumerator CoordinateParallelGenerationAndProcessing() { // Generate first list, then start processing it right away yield return GenerateList(list1, 1000); StartCoroutine(Coroutine2(list1)); // Pass the ready list to Coroutine2 // While Coroutine2 is processing list1, generate list2 yield return GenerateList(list2, 1000); StartCoroutine(Coroutine2(list2)); // Process list2 once it's ready } // Modified Coroutine2 to accept a single list IEnumerator Coroutine2(List<YourDataType> listToProcess) { foreach (var item in listToProcess) { ProcessItem(item); if (listToProcess.IndexOf(item) % 50 == 0) yield return null; } } // Reuse the same GenerateList coroutine from Solution 1 IEnumerator GenerateList(List<YourDataType> targetList, int totalItems) { for (int i = 0; i < totalItems; i++) { targetList.Add(CreateYourDataItem()); if (i % 100 == 0) yield return null; } }
Key takeaways for smooth coroutines:
- Always split heavy loops with
yield return null: This lets Unity handle other tasks (like rendering, input) between chunks of work, preventing freezes. - Control execution order: If one coroutine depends on another's output, either wait for the dependent coroutine to finish or pass data incrementally when it's ready.
- Avoid unyielded loops in coroutines: A coroutine without yields is just a regular function that blocks the main thread—defeats the purpose of using coroutines for lag reduction!
内容的提问来源于stack exchange,提问作者user4676310

