首页 > 解决方案 > 协程统一 - 不可预知的行为

问题描述

任何人都可以解释我的代码的问题吗?

我在程序开始时启动了两个协程。这些是:

loader = StartCoroutine(loadobjectsfromfile);
buffer = StartCoroutine(setBufferToSpesificLocation(0));

简要说明 loadobjectsfromfile 从文件中读取 obj 并将它们添加到List<GameObjects> loadedObject. Ant 它读取更多,直到缓冲区已满。

 IEnumerator loadobjectsfromfile(string filepath, List<GameObject> objs)
    {       while(...)
            {
                // other code lines
               // ...
                loadedObject.Add(gam);
                while (full_)
                {
                    yield return null;
                }  
                k++;
                yield return null;
            } }

setBufferTheSpesificLocation 将列表中的对象添加到 buffer[] 数组。它还会放置对象,直到缓冲区已满。

 IEnumerator setBufferToSpesificLocation(int startPoint)
    {

        for ( foo = startPoint; foo < loadedObject.Count; foo++)
        {

            while (full_)
            {
                yield return null;
            }

            put(loadedObject[foo]);

            yield return null;
        }

    }

 void put(GameObject frame)
    {

        buff_[head_] = frame;
        head_ = (head_ + 1) % bufferSize;
        full_ = head_ == tail_;


    }

最后一部分,我们如何清空缓冲区?我调用 display 调用的其他协程。

IEnumerator displayMesh(GameObject[] objs)
    {


        while (!empty())
        {
            // other lines
            full_ = false; // have a free space
        }

    }

好吧,如果我启动前两个协程,然后调用最后一个协程(没有问题。我的代码运行良好。但是我遇到了一个新案例的问题。

loader = StartCoroutine(loadobjectsfromfile);
buffer = StartCoroutine(setBufferToSpesificLocation(0));
StopCoroutine(buffer);
buffer = StartCoroutine(setBufferToSpesificLocation(50)); // 
play = StartCoroutine(displayMesh(buff_));

问题是,在调用第二个缓冲区协程后,加载程序在这种情况下不起作用。当“ ( foo = startPoint; foo < loadedObject.Count; foo++)”结束时,加载程序正在工作。

我不明白。我认为,如果full_为假,加载器和缓冲区都必须工作,但只有缓冲区在工作,加载器正在等待“缓冲区 for{} 循环”

标签: unity3dcoroutine

解决方案


我不知道你为什么要启动一个协程然后立即停止它。当您调用 StartCoroutine 时,它​​将运行该例程,直到它达到产量。在将例程运行到第一个 yield 后,它将运行启动协程的下一行。

检查有关事件函数执行顺序的链接: https ://docs.unity3d.com/Manual/ExecutionOrder.html#Coroutines

这一篇关于协程 https://docs.unity3d.com/Manual/BestPracticeUnderstandingPerformanceInUnity3.html

因此,在您的情况下,事情将按以下顺序发生:

1:启动协程

loader = StartCoroutine(loadobjectsfromfile);

2:运行到第一个产量

 IEnumerator loadobjectsfromfile(string filepath, List<GameObject> objs)
    {       while(...)
            {
                // other code lines
               // ...
                loadedObject.Add(gam);
                while (full_)
                {
                    yield return null;
                }  
                k++;
                yield return null; //<<<<<<<<<<<<<<HERE<<<<<<<<<<<<<<<<<<<<
            } }

3:启动下一个协程

buffer = StartCoroutine(setBufferToSpesificLocation(0));

4:运行到第一个产量

 IEnumerator setBufferToSpesificLocation(int startPoint)
    {

        for ( foo = startPoint; foo < loadedObject.Count; foo++)
        {

            while (full_)
            {
                yield return null;
            }

            put(loadedObject[foo]);

            yield return null; //<<<<<<<<<<<<<<HERE<<<<<<<<<<<<<<<<<<<<
        }

    }

4:停止缓冲程序

StopCoroutine(buffer);

5:再次启动缓冲区,但现在 startPoint 参数设置为 50

buffer = StartCoroutine(setBufferToSpesificLocation(50));

6:跑到第一个产量???不,foo = startPoint 现在是 50...

IEnumerator setBufferToSpesificLocation(int startPoint)
    {
        //it will skip the loop as foo is 50 and loadedObject.Count is 1 (probabbly)
        for ( foo = startPoint; foo < loadedObject.Count; foo++) 
        {
            //code...
        }

        //WILL END THE COROUTINE
    }

推荐阅读