什么是 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);
}
}
我正在尝试使用协程在每次交换之间添加一个延迟,因为没有“Waitforseconds”,所有值同时移动,而且它们都在错误的位置结束,即使通过调试数组是排序。我还注意到 StartCoroutine 之后的代码继续 运行,也许这就是为什么它们最终出现在错误位置的原因。我只想知道是否有协程的替代方案,我可以在 LeanTween 循环期间暂停整个过程。或者我以错误的方式使用协程。提前致谢。
这里的问题是您在同一帧上开始所有交换,而不是按顺序进行。这是因为你多次调用 StartCoroutine
而没有 returning 退出更新,(或者在它们之间产生 returning 在协程的情况下)。
你应该让 Partition
成为协程,然后在每次调用 Swap
时让步,这样它会等待每个 Swap
协程完成后再继续。另外,在每次交换结束时等待。
由于协程的 return 值保留用于管理控制流,您可以改为向协程发送委托以调用结果。为此使用 Action<int>
。
一共:
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
调用按顺序发生而不是同时发生,问题会变得有点棘手,因为您需要能够在它们之间产生 return!
因此,要使用协程来实现这一点,您还需要将 QuickSort
和 callback
制作成协程。您不能在匿名函数中使用 yield returns,因此回调需要是一个方法,它接受它使用的每个变量的参数,然后 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
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 之后的代码继续 运行,也许这就是为什么它们最终出现在错误位置的原因。我只想知道是否有协程的替代方案,我可以在 LeanTween 循环期间暂停整个过程。或者我以错误的方式使用协程。提前致谢。
这里的问题是您在同一帧上开始所有交换,而不是按顺序进行。这是因为你多次调用 StartCoroutine
而没有 returning 退出更新,(或者在它们之间产生 returning 在协程的情况下)。
你应该让 Partition
成为协程,然后在每次调用 Swap
时让步,这样它会等待每个 Swap
协程完成后再继续。另外,在每次交换结束时等待。
由于协程的 return 值保留用于管理控制流,您可以改为向协程发送委托以调用结果。为此使用 Action<int>
。
一共:
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
调用按顺序发生而不是同时发生,问题会变得有点棘手,因为您需要能够在它们之间产生 return!
因此,要使用协程来实现这一点,您还需要将 QuickSort
和 callback
制作成协程。您不能在匿名函数中使用 yield returns,因此回调需要是一个方法,它接受它使用的每个变量的参数,然后 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