解決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函數經過一些嵌套的測試,使用起來還算穩定。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM