【问题标题】:What are Unity Coroutines and what am I doing wrong?什么是 Unity Coroutines,我做错了什么?
【发布时间】:2021-03-20 10:57:05
【问题描述】:
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);
        
    }

}

我正在尝试使用协程在每次交换之间添加延迟,因为没有“Waitforseconds”,所有值都会同时移动,即使通过调试对数组进行排序,它们也会最终出现在错误的位置。我还注意到 StartCoroutine 之后的代码继续运行,也许这就是它们最终出现在错误位置的原因。我只是想知道如果有一个 Coroutine 的替代方案,我可以在 LeanTween 循环期间暂停整个事情。或者我以错误的方式使用协程。提前致谢。

【问题讨论】:

  • 恕我直言简化您的协同程序,因此它负责一个对象。我猜不同的实例正在覆盖彼此的变化。

标签: c# unity3d coroutine


【解决方案1】:

这里的问题是您在同一帧上开始所有交换,而不是按顺序进行。这是因为您多次调用StartCoroutine 而没有从更新中返回(或者在协程的情况下返回)。

您应该将Partition 设为协程,然后在每次调用Swap 时让步,因此它会等待每个Swap 协程完成后再继续。另外,请在每次交换结束时等待。

由于协程的返回值是为管理控制流而保留的,因此您可以改为向协程发送委托以调用结果。为此使用Action&lt;int&gt;

总共:

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));  
    }
}

如果您希望相邻的QuickSort 调用按顺序而不是同时发生,那么问题会变得有点棘手,因为您需要能够在它们之间产生返回!

因此,要使用协程来实现这一点,您还需要将 QuickSortcallback 变成协程。您不能在匿名函数内部使用 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

【讨论】:

  • 非常感谢!两种解决方案都运行良好,我认为这就是我所追求的。再次感谢
猜你喜欢
  • 1970-01-01
  • 2011-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
  • 2021-04-19
  • 2017-03-13
相关资源
最近更新 更多