Search code examples
c#coroutineunity-game-engine

Wait for a coroutine to finish before moving on with the function C# Unity


I was working on making a unit move through a grid in Unity2d. I got the movement to work without problems. I would want the function MovePlayer to wait until the coroutine is finished before moving on, so the program will wait until the player has finished the movement before issuing more orders.

Here is my code: public class Player : MonoBehaviour {

public Vector3 position;
private Vector3 targetPosition;

private float speed;

void Awake ()
{
    speed = 2.0f;
    position = gameObject.transform.position;
    targetPosition = position;
    GameManager.instance.AddPlayerToList(this);                     //Register this player with our instance of GameManager by adding it to a list of Player objects. 
}

//Function that moves the player, takes a list of nodes as path
public void MovePlayer(List<Node> path)
{
    StartCoroutine(SmoothMovement(path));
    //Next step should wait until SmoothMovement is finished
}

private IEnumerator SmoothMovement(List<Node> path)
{
    float step = speed * Time.deltaTime;

    for (int i = 0; i < path.Count; i++)
    {
        targetPosition = new Vector3(path[i].coordinatesX, path[i].coordinatesY, 0f);

        float sqrRemainingDistance = (transform.position - targetPosition).sqrMagnitude;

        while (sqrRemainingDistance > float.Epsilon)
        {
            transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
            sqrRemainingDistance = (transform.position - targetPosition).sqrMagnitude;
            yield return null;
        }

        position = transform.position;
    }

}

Solution

  • You can not wait for a coroutine in a function in the main thread, otherwise your game will freeze until your function ends.

    Why don't you call your next step at the end of your coroutine?

    private IEnumerator SmoothMovement(List<Node> path)
    {
        float step = speed * Time.deltaTime;
    
        for (int i = 0; i < path.Count; i++)
        {
            targetPosition = new Vector3(path[i].coordinatesX, path[i].coordinatesY, 0f);
    
            float sqrRemainingDistance = (transform.position - targetPosition).sqrMagnitude;
    
            while (sqrRemainingDistance > float.Epsilon)
            {
                transform.position = Vector3.MoveTowards(transform.position, targetPosition, step);
                sqrRemainingDistance = (transform.position - targetPosition).sqrMagnitude;
                yield return null;
            }
    
            position = transform.position;
        }
        //Next Step
    }