zoukankan      html  css  js  c++  java
  • 解决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函数经过一些嵌套的测试,使用起来还算稳定。

  • 相关阅读:
    OrCAD原理图封装规则
    web的脚本安全-CSRF
    web的脚本安全-XSS
    数据库中左右连接
    如何解决Java.lang.NoClassDefFoundError
    css垂直居中
    网上免费的web service地址
    JS 正则表达式用法
    jQuery实现滚动条向下拉到一定的程度,然后这层就一直占着不管滚动条如何向下拉都不动了的效果
    Robot Framework + Selenium2Library环境下,结合Selenium Grid实施分布式自动化测试
  • 原文地址:https://www.cnblogs.com/hont/p/6533248.html
Copyright © 2011-2022 走看看