解决Unity协程无法同步返回的问题

Unity的协程是轻量的异步解决方案,但是每调用一次yield就必须等下一帧才能继续,这一点带来了很多约束。

 

比如如下代码:

复制代码
void OnEnable()
{
    StartCoroutine(_Do());
}

IEnumerator _Do()
{
    Debug.Log("[A]Frame " + Time.frameCount);
    yield return null;
    Debug.Log("[B]Frame " + Time.frameCount);
}
复制代码

 

 

 

当然,也会想到用一些Trick欺骗过去

复制代码
IEnumerator Start()
{
    Debug.Log("[0]frame: " + Time.frameCount);

    yield return Foo1();

    yield return Foo2();
}

IEnumerator Foo1()
{
    Debug.Log("[1]frame: " + Time.frameCount);
    if (Time.time < 0)//always false
        yield return null;
    Debug.Log("[2]frame: " + Time.frameCount);
}

IEnumerator Foo2()
{
    Debug.Log("[3]frame: " + Time.frameCount);

    yield return null;
}
复制代码

可是编译器并不吃这一套

 

 

 

那么解决方法也很简单,就是用迭代器再封装一层。

并把yield return true作为非异步返回的标记:

 

复制代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

public class CoroutineTest : MonoBehaviour
{
    void OnEnable()
    {
        StartCoroutine(ToFixedCoroutine(_Do()));
    }

    IEnumerator _Do()
    {
        Debug.Log("[A]Frame " + Time.frameCount);
        yield return true;
        Debug.Log("[B]Frame " + Time.frameCount);
    }

    public static IEnumerator ToFixedCoroutine(IEnumerator enumerator)
    {
        var parentsStack = new Stack<IEnumerator>();
        var currentEnumerator = enumerator;

        parentsStack.Push(currentEnumerator);

        while (parentsStack.Count > 0)
        {
            currentEnumerator = parentsStack.Pop();

            while (currentEnumerator.MoveNext())
            {
                var subEnumerator = currentEnumerator.Current as IEnumerator;
                if (subEnumerator != null)
                {
                    parentsStack.Push(currentEnumerator);
                    currentEnumerator = subEnumerator;
                }
                else
                {
                    if (currentEnumerator.Current is bool && (bool)currentEnumerator.Current) continue;
                    yield return currentEnumerator.Current;
                }
            }
        }
    }
}
复制代码

 

 

 

 

这样就可以同步返回了

ToFixedCoroutine函数经过一些嵌套的测试,使用起来还算稳定。

 

posted @   HONT  阅读(3330)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示
回到顶部