我想使用游戏对象进行快速排序的可视化。问题是,当我将方法放在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,则递归不起作用。但是如果处于无效状态,它正在工作,则虚空不会等待动画方法完成。它同时执行。
答案 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});