简体   繁体   English

什么是 Unity Coroutines,我做错了什么?

[英]What are Unity Coroutines and what am I doing wrong?

int Partition(GameObject[] list, int left, int right)
{
    GameObject pivot = list[right];

    //GameObject temp;

    int i = left - 1;

    for (int j = left; j <= right - 1; j++)
    {
        if (list[j].transform.position.y <= pivot.transform.position.y)
        {
            i++;
            StartCoroutine(Swap(list, i, j));

        }
    }
    StartCoroutine(Swap(list, i+1, right));
    return i + 1;
}

IEnumerator Swap(GameObject[] list, int i, int j)
{
    temp = list[i];
    list[i] = list[i+1];
    list[i+1] = temp;

    LeanTween.color(list[i], Color.red, 1f);
    LeanTween.color(list[i+1], Color.red, 1f);
    yield return new WaitForSeconds(1.5f);
    LeanTween.color(list[i], Color.white, 1f);
    LeanTween.color(list[i+1], Color.white, 1f);

    tempPosition = list[i].transform.localPosition;

    LeanTween.moveLocalX((list[i]), list[i+1].transform.localPosition.x, 1);

    LeanTween.moveLocalZ(list[i], -3, .5f).setLoopPingPong(1);

    LeanTween.moveLocalX((list[i+1]), tempPosition.x, 1);

    LeanTween.moveLocalZ(list[i+1], 3, .5f).setLoopPingPong(1);
}


void QuickSort(GameObject[] list, int left, int right)
{ 
    int pivot;
    if(left < right)
    {
        pivot = Partition(list, left, right);

        QuickSort(list, left, pivot - 1);

        QuickSort(list, pivot + 1, right);
        
    }

}

I'm trying to use Coroutines to add a Delay between each swap as without "Waitforseconds" all of the values move at the same time and also they all end up at the wrong location even though through debuging the array is sorted.我正在尝试使用协程在每次交换之间添加延迟,因为没有“Waitforseconds”,所有值都会同时移动,即使通过调试对数组进行排序,它们也会最终出现在错误的位置。 I also noticed that the code after StartCoroutine continues to run, maybe thats why they end up in wrong location.我还注意到 StartCoroutine 之后的代码继续运行,也许这就是它们最终出现在错误位置的原因。 I just want to know what if there is an alternative to Coroutine where I can pause the whole thing for the duration of the LeanTween Loop.我只是想知道如果有一个 Coroutine 的替代方案,我可以在 LeanTween 循环期间暂停整个事情。 Or I'm using coroutines them in a wrong way.或者我以错误的方式使用协程。 Thanks in advance.提前致谢。

The problem here is that you're starting all of the swaps on the same frame instead of doing them in sequence.这里的问题是您在同一帧上开始所有交换,而不是按顺序进行。 This is because you call StartCoroutine a bunch of times without returning out of Update, (or yield returning in the case of a coroutine) between them.这是因为您多次调用StartCoroutine而没有从 Update 中返回(或者在协程的情况下返回 yield)。

You should make Partition a coroutine, then yield on each call of Swap so it waits for each Swap coroutine to complete before continuing.您应该让Partition成为协程,然后在每次调用Swap时让出,以便等待每个Swap协程完成后再继续。 Also, wait at the end of each swap.另外,请在每次交换结束时等待。

Since a coroutine's return value is reserved for managing the flow of control, you can instead send the coroutine a delegate to call with the result.由于协程的返回值是为管理控制流而保留的,因此您可以向协程发送委托以调用结果。 use Action<int> for that.为此使用Action<int>

Altogether:共:

IEnumerator Partition(GameObject[] list, int left, int right, Action<int> onComplete)
{
    GameObject pivot = list[right];

    //GameObject temp;

    int i = left - 1;

    for (int j = left; j <= right - 1; j++)
    {
        if (list[j].transform.position.y <= pivot.transform.position.y)
        {
            i++;
            yield return Swap(list, i, j);

        }
    }
    yield return Swap(list, i+1, right);
    onComplete.Invoke(i + 1);
}

IEnumerator Swap(GameObject[] list, int i, int j)
{
    temp = list[i];
    list[i] = list[i+1];
    list[i+1] = temp;

    LeanTween.color(list[i], Color.red, 1f);
    LeanTween.color(list[i+1], Color.red, 1f);
    yield return new WaitForSeconds(1.5f);
    LeanTween.color(list[i], Color.white, 1f);
    LeanTween.color(list[i+1], Color.white, 1f);

    tempPosition = list[i].transform.localPosition;

    LeanTween.moveLocalX((list[i]), list[i+1].transform.localPosition.x, 1);

    LeanTween.moveLocalZ(list[i], -3, .5f).setLoopPingPong(1);

    LeanTween.moveLocalX((list[i+1]), tempPosition.x, 1);

    LeanTween.moveLocalZ(list[i+1], 3, .5f).setLoopPingPong(1);
    yield return new WaitForSeconds(1.5f);
}



void QuickSort(GameObject[] list, int left, int right)
{ 
    if(left < right)
    {
        Action<int> callback = pivot =>
        {
            QuickSort(list, left, pivot - 1);
            QuickSort(list, pivot + 1, right);
        };

        StartCoroutine(Partition(list, left, right, callback));  
    }
}

If you want the adjacent QuickSort calls to occur in sequence instead of simultaneously, the problem gets a little trickier, since you would need to be able to yield return in between them!如果您希望相邻的QuickSort调用按顺序发生而不是同时发生,那么问题会变得有点棘手,因为您需要能够在它们之间产生 return!

So, to implement this using coroutines, you would need to make QuickSort and callback into coroutines as well.因此,要使用协程实现这一点,您还需要在协程中进行QuickSortcallback You can't use yield returns inside of anonymous functions, so callback needs to instead be a method that accepts parameters for every variable it uses, and then Partition needs to provide them accordingly:您不能在匿名函数中使用 yield 返回,因此 callback 需要改为接受它使用的每个变量的参数的方法,然后Partition需要相应地提供它们:

IEnumerator Partition(GameObject[] list, int left, int right)
{
    GameObject pivot = list[right];

    //GameObject temp;

    int i = left - 1;

    for (int j = left; j <= right - 1; j++)
    {
        if (list[j].transform.position.y <= pivot.transform.position.y)
        {
            i++;
            yield return Swap(list, i, j);

        }
    }
    yield return Swap(list, i+1, right);
    yield return QuickSortCallback(list, left, right, i + 1);
}

IEnumerator QuickSortCallback(GameObject[] list, int left, int right, int pivot)
{
    yield return QuickSort(list, left, pivot - 1);
    yield return QuickSort(list, pivot + 1, right);
}

IEnumerator QuickSort(GameObject[] list, int left, int right)
{ 
    if(left < right)
    {
        yield return Partition(list, left, right));  
    }
}

/* unchanged from above, just including here for convenience */
IEnumerator Swap(GameObject[] list, int i, int j)
{
    temp = list[i];
    list[i] = list[i+1];
    list[i+1] = temp;

    LeanTween.color(list[i], Color.red, 1f);
    LeanTween.color(list[i+1], Color.red, 1f);
    yield return new WaitForSeconds(1.5f);
    LeanTween.color(list[i], Color.white, 1f);
    LeanTween.color(list[i+1], Color.white, 1f);

    tempPosition = list[i].transform.localPosition;

    LeanTween.moveLocalX((list[i]), list[i+1].transform.localPosition.x, 1);

    LeanTween.moveLocalZ(list[i], -3, .5f).setLoopPingPong(1);

    LeanTween.moveLocalX((list[i+1]), tempPosition.x, 1);

    LeanTween.moveLocalZ(list[i+1], 3, .5f).setLoopPingPong(1);
    yield return new WaitForSeconds(1.5f);
}

See here for more information浏览此处获取更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM