mjavier
mjavier

Reputation: 13

How to wait for a method to finish before moving on the next line of code in Unity?

I want to make an Visualization of quick sort using game objects. The problem is, when I put the method inside the quicksort method it doesn't wait for the animation to finish. The code executes all the lines at the same time.

I want to make the method execute first then proceed to the next line. I already tried the IEnumerator function but the sequence is rearranged if I use yield return StartCoroutine ( myfunction() ); quick sort is in a recursive sequence. At first the animation works but when the recursion happens, the yield return is not working any more.

Here is my code in C#:

IEnumerator swapElement(int e1, int e2)
{
    swap = true;<br>
    go1 = GameObject.Find ("Element" + e1);<br>
    go2 = GameObject.Find ("Element" + e2);

    go1xpos = go1.GetComponent<Transform> ().transform.position.x;
    go2xpos = go2.GetComponent<Transform> ().transform.position.x;
    go1ypos = go1.GetComponent<Transform> ().transform.position.y;

    x1ps = go1xpos;
    x2ps = go2xpos;


    go1.GetComponent<Transform> ().transform.position = new Vector3 (x2ps, go1ypos);
    go2.GetComponent<Transform> ().transform.position = new Vector3 (x1ps, go1ypos);
    yield return new WaitForSeconds (5);

    Debug.Log ("INSIDE SWAP : LEFT : " + e1 + " RIGHT : " + e2);

}



Sort Method:

int l, r;

int partition(int[] numbers, int left, int right)
{

    int pivot = numbers [ (left + right) / 2];

    while (true) 
    {
        while (numbers [left] < pivot) left++;
        while (numbers [right] > pivot) right--;

        if (left < right) 
        {
            int temp = numbers [right];
            numbers [right] = numbers [left];
            numbers [left] = temp;

            //Debug.Log ("LEFT : " + left + " RIGHT : " + right);

            swapElement (left, right);

        }
        else 
        {
            return right;
        }

    }

}


void quickSort(int[] arr, int left, int right)
{

    if (left < right) 
    {
        int piv = partition (arr, left, right);

        if (piv > 1) quickSort (arr, left, piv - 1);
        if (piv + 1 < right) quickSort (arr, piv + 1, right);
    }

}

I already tried startcoroutine( swap (left, right) ), but no luck.

I can put the animation inside the swap method but even then it is still the same: It executes at the same time.

additional information :
if I use IEnumerator, the recursion is not working. but if in void, It is working however, the void is not waiting for the animation method to finish. it executes at the same time.

Upvotes: 0

Views: 2410

Answers (1)

Leo Bartkus
Leo Bartkus

Reputation: 1945

You need to return the coroutine's IEnumerator all the way up to the top of the callstack. I would start with turning quicksort() into a coroutine.

IEnumerator quickSort(QuickSortArgs args)
{

    if (left < right) 
    {
        int piv = partition (args.arr, args.left, args.right);
        yield return new WaitForSeconds (5);
        if (piv > 1) yield return quickSort (args.arr, args.left, piv - 1);
        if (piv + 1 < right) yield return quickSort (args.arr, piv + 1, args.right);

    }

}

If you want to wait down in the swaps, you would need to return the IEnumerator from each call in the callstack down to it.

To smoothly animate them, something more like this. You need to include the time deltatime, and you can use Vector3.Lerp instead of making your own lerp.

IEnumerator swapElement(SwapElementArgs args) {

    GameObject go1 = GameObject.Find ("Element" + args.ele1);
    GameObject go2 = GameObject.Find ("Element" + args.ele2);

    float go1_pos = go1.transform.position;
    float go2_pos = go2.transform.position;

    float t = 0f;

    while(t < 1.0f){

        t += Time.deltaTime/args.speed;
        var go1_newpos = Vector3.Lerp(go1_pos, go2_pos, t);
        var go2_newpos = Vector3.Lerp(go2_pos, go1_pos, t);

        go1.transform.position = go1_newpos;
        go2.transform.position = go2.newpos;

        yield return new WaitForSeconds(0.1);

    }

}

Then you would start this coroutine in the sort method instead of just calling it.

StartCoroutine("swapElement", new SwapElementArgs(){ele1=left, ele2=right, speed=1.0f});

Upvotes: 2

Related Questions