使循环等待操作完成

时间:2015-04-17 15:34:00

标签: c# loops unity3d coroutine

我在Unity3d工作(这更像是一个C#问题,所以我怀疑这是一个问题)。我正在研究像你在文明中找到的运动系统。我有一个循环设置,这样你每回合可以移动2个方格。这很好用。我点击了10个街区外的广场,需要5个回合才能到达那里。现在我试图在块之间制作pawn lerp。我有lerp工作,问题是,它从当前的磁贴跳转到第一个磁贴,然后转换到它应该是的第二个磁贴。我使用协程来完成这项工作而不是更新功能(因为更新会导致它只是到达最终目的地,而不是从当前,到第一,到第二)。所以我遇到的是通过pawn所经历的每次移动的循环,不等待协程在继续其自己的循环之前完成。这是代码

public void MoveNextTile()
{
    float remainingMoves = moveSpeed;
    while (remainingMoves > 0)
    {

        if (currentPath == null)
            return;
        //Get the cost from current tile to next tile
        remainingMoves -= map.CostToEnterTile(currentPath[0].x, currentPath[0].y, currentPath[1].x, currentPath[1].y);

        //Move us to the next tile in the sequence
        toVector = map.TileCoordToWorldCoord(currentPath[1].x, currentPath[1].y);
        Vector3 fromVec = transform.position;
        StartCoroutine(MoveObject(fromVec, toVector, 1.0f));


        //transform.position = map.TileCoordToWorldCoord(currentPath[1].x, currentPath[1].y);

        //Remove the old current tile

        this.tileX = currentPath[0].x;
        this.tileY = currentPath[0].y;
        currentPath.RemoveAt(0);
        if (currentPath.Count == 1)
        {
            this.tileX = currentPath[0].x;
            this.tileY = currentPath[0].y;
            currentPath = null;
        }


    }

}
IEnumerator MoveObject(Vector3 source, Vector3 target, float overTime)
{
    float startTime = Time.time;
    while (Time.time < startTime + overTime)
    {
        transform.position = Vector3.Lerp(source, target, (Time.time - startTime) / overTime);
        yield return null;
    }
    transform.position = target;

}

我知道这是一个菜鸟问题。我以前从未需要在C#中这样做。提前感谢所有帮助

1 个答案:

答案 0 :(得分:3)

我建议您研究协程如何工作。

你的协程没有完全执行,然后返回完成MoveNextTile函数的其余部分。它实际执行到第一个yield语句,然后继续执行MoveNextTile。每个后续帧将继续运行协程的一个“步骤”,直到下一个yield语句尝试复制异步方法。

您要做的是告诉您的程序明确等待您的协程完成。这样做;

yield return StartCoroutine(MoveObject(fromVec,toVector,1.0f));

当然,您只能在IEnumerator中使用此语句。因此,您必须将void MoveNextTile函数更改为IEnumerator MoveNextTile。你最终会得到以下内容;

public IEnumerator MoveNextTile() {

    // Ommited
    while (remainingMoves > 0) {
        //Ommited
        yield return StartCoroutine(MoveObject(fromVec, toVector, 1.0f));
        // Now MoveNextTile will continue after your MoveObject coroutine finishes.
    }
}