如何在继续使用Unity中的下一行代码之前等待方法完成?

时间:2017-04-03 12:31:29

标签: c# unity3d

我想使用游戏对象进行快速排序的可视化。问题是,当我将方法放在quicksort方法中时,它不会等待动画完成。代码同时执行所有行。

我想先让方法执行,然后继续下一行。我已经尝试过IEnumerator函数,但如果我使用yield return StartCoroutine ( myfunction() ),则会重新排列序列。快速排序是递归序列。首先动画可以工作,但是当递归发生时,yield return不再起作用。

这是我在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);

}



排序方法:

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

}

我已经尝试了startcoroutine( swap (left, right) ),但没有运气。

我可以将动画放在swap方法中,但即便如此,它仍然是相同的:它同时执行。

附加信息:
如果我使用IEnumerator,则递归不起作用。但是如果处于无效状态,它正在工作,则虚空不会等待动画方法完成。它同时执行。

1 个答案:

答案 0 :(得分:2)

你需要将coroutine的IEnumerator一直返回到callstack的顶部。我首先将quicksort()转换为协程。

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

    }

}

如果你想在交换中等待,你需要将callnack中每次调用的IEnumerator返回到它。

为了平滑地制作动画,更像是这样的东西。您需要包含时间deltatime,并且可以使用Vector3.Lerp而不是制作自己的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);

    }

}

然后你将在sort方法中启动这个协程,而不是仅仅调用它。

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