简体   繁体   中英

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. I also noticed that the code after StartCoroutine continues to run, maybe thats why they end up in wrong location. 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. 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.

You should make Partition a coroutine, then yield on each call of Swap so it waits for each Swap coroutine to complete before continuing. 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.

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!

So, to implement this using coroutines, you would need to make QuickSort and callback into coroutines as well. 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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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