2017-04-03 396 views
0

我想使用遊戲對象進行快速排序的可視化。問題是,當我將該方法放入quicksort方法中時,它不會等待動畫完成。該代碼同時執行所有行。如何在Unity中移動下一行代碼之前等待方法結束?

我想讓該方法先執行然後繼續下一行。我已經嘗試過IEnumerator函數,但是如果使用yield return StartCoroutine (myfunction()),則序列會重新排列;快速排序是按遞歸順序進行的。起初動畫是有效的,但是當遞歸發生時,收益回報不再起作用。

這是我在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,則遞歸不起作用。但是如果在無效的情況下,它正在工作,虛空並不等待動畫方法完成。它同時執行。

回答

2

您需要將協程的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); 

    } 

} 

如果你要等待向下掉期,則需要從每個呼叫的調用堆棧返回的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); 

    } 

} 

然後,您將在排序方法中啓動此協程,而不是僅調用它。

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

感謝您的回覆先生。生病先嚐試一下。生病後發送反饋。 – mjavier

+0

他們仍然在同一時間先生。生病包括我的動畫代碼在這個問題上 – mjavier

+0

如果您將WaitForSeconds移動到分區調用之後,該怎麼辦?我不希望它能夠順利進行動畫製作,但是它至少是否按照預期的順序進行了交換? –

相關問題