Make the loop wait for the action to complete

I'm working in Unity3d (this is more of a C # question, so I doubt this is a problem). I'm working on a movement system like you would find in Civilization. I have a loop setup so you can move 2 squares per turn. This works great. I click on a square 10 blocks away and it takes 5 turns to get there. Now I'm trying to make a pawn strap between the blocks. I have a lerp to work with, the problem is that it jumps from the current tile to the 1st tile and then goes to the 2nd tile where it should be. I used a coroutine to do this job instead of an update function (since the update would simply execute the final destination instead of the current, first, second). So what im running in a loop that goes through every pawn move, doesn't wait for the coroutine to complete,before continuing your own cycle. Here is the code

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;

}

      

I know this is a nob question. I've just never had to do this in C # before. Thank you in advance for your help.

+3


source to share


1 answer


I suggest you study how coroutines work.

Your coroutine is not fully executed and then returns to complete the remainder of the MoveNextTile function. It actually runs until the first yield statement and then continues with MoveNextTile. Each subsequent frame will continue to execute one "step" of the coroutine until the next yield statement in an attempt to replicate asynchronous methods.

What you want to do is tell your program to explicitly wait for your coroutine to finish. For this



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

Of course, you can only use this operator inside IEnumerator. Thus, you will need to change the void MoveNextTile function to IEnumerator MoveNextTile. You get something like this:

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.
    }
}

      

+3


source







All Articles