如何确保一个协程在另一个 运行 之前完成?

How to ensure that one coroutine completes before another is run?

我有两个协程。一个有几个协程。在第二个协程在 Start() 方法中运行之前,第一个协程不会等待第二个协程完成。请看下面的代码。

void Start() {
    StartCoroutine(DrawLineWithDuration (3.0f));
    StartCoroutine (changeLinePos (2.0f));
}

IEnumerator DrawLineWithDuration (float duration)  {

    lr.positionCount = 1;
    lr.SetPosition(0, GetPoint(0));

    float waitDur = duration / numPoints;

    for (int i = 1; i < numPoints + 1; i++) {
        float t = i / (float)numPoints;
        lr.positionCount = i+1;
        lr.SetPosition(i, GetPoint(t));

        yield return new WaitForSeconds(waitDur);
    }
}

IEnumerator moveToPosition1(Vector3 toPosition, float duration)
{

    float counter = 0;

    Vector3 startPos = points[1];

    while (counter < duration)
    {
        counter += Time.deltaTime;
        points[1] = Vector3.Lerp(startPos, toPosition, counter / duration);
        yield return null;
    }

}

IEnumerator moveToPosition2(Vector3 toPosition, float duration)
{
    float counter = 0;
    Vector3 startPos = points[2];

    while (counter < duration)
    {
        counter += Time.deltaTime;
        points[2] = Vector3.Lerp(startPos, toPosition, counter / duration);
        yield return null;
    }
}


IEnumerator moveToOriginal1(Vector3 toPosition, float duration)
{

    float counter = 0;

    Vector3 startPos = points[1];

    while (counter < duration)
    {
        counter += Time.deltaTime;
        points[1] = Vector3.Lerp(startPos, toPosition, counter / duration);
        yield return null;
    }

}

IEnumerator moveToOriginal2(Vector3 toPosition, float duration)
{
    float counter = 0;
    Vector3 startPos = points[2];

    while (counter < duration)
    {
        counter += Time.deltaTime;
        points[2] = Vector3.Lerp(startPos, toPosition, counter / duration);
        yield return null;
    }
}


IEnumerator changeLinePos(float waitTime)   {

    yield return new WaitForSeconds(waitTime);

    while (isRepeating) {
        StartCoroutine (moveToPosition1 (newPos1, moveDuration));
        StartCoroutine (moveToPosition2 (newPos2, moveDuration));
        yield return new WaitForSeconds (betweenPosMoveDelay);

        StartCoroutine (moveToOriginal1 (oriPos1, moveDuration));
        StartCoroutine (moveToOriginal2 (oriPos2, moveDuration));

        yield return new WaitForSeconds (betweenPosMoveDelay);
    }

}

Start() 内,我如何确保 StartCoroutine(DrawLineWithDuration (3.0f));StartCoroutine (changeLinePos (2.0f)); 开始之前以给定的持续时间完成。同样在 changeLinePos(float waitTime) 中,我如何确保 moveToPosition1moveToPosition2moveToOriginal1moveToOriginal1 以及 moveToOriginal2 之前完成?

其实很简单,你可以把yield return StartCoroutine(DrawLineWithDuration (3.0f));作为changeLinePos的第一行,像这样:

void Start() {    
    StartCoroutine (ChangeLinePos (2.0f));
}

IEnumerator ChangeLinePos(float waitTime)   {
    yield return StartCoroutine(DrawLineWithDuration (3.0f));
    while (isRepeating) {
        StartCoroutine (MoveToOriginal1 (oriPos1, moveDuration));
        StartCoroutine (MoveToOriginal2 (oriPos2, moveDuration));
        yield return new WaitForSeconds (betweenPosMoveDelay);
    }
}

IEnumerator MoveToOriginal1(Vector3 toPosition, float duration) {
    yield return StartCoroutine (MoveToPosition1 (newPos1, moveDuration));
    //Rest of MoveToOriginal1 code
}

IEnumerator MoveToOriginal2(Vector3 toPosition, float duration) {
    yield return StartCoroutine (MoveToPosition2 (newPos2, moveDuration));
    //Rest of MoveToOriginal1 code
}

采用这种结构,时序如下:

  • ChangeLinePos 开始于 Start()
  • 第一行开始DrawLineWithDuration并停止执行ChangeLinePos直到前者完成
  • DrawLineWithDuration完成,如果isRepeating==true,代码开始MoveToOriginal1MoveToOriginal2同步
  • MoveToOriginal1MoveToOriginal2 都开始 MoveToPosition1MoveToPosition2 并等待最后两个完成。

我离开了 while 因为它似乎受到协程之外的某些东西的影响,所以请确保 isRepeating 在需要时更改为 false,如果不是 MoveToOriginal1MoveToOriginal2 协程将始终启动,直到应用程序停止。