move object from A to B and notify caller when done

I would like to create a grid based 3D game and the movement itself will always be the same (the animations differ of course). I created a basic script to handle the movement of every moveable GameObject

public class Movement : MonoBehaviour
{
    [SerializeField]
    float movementSpeed;

    Vector2Int currentPosition;

    void Awake()
    {
        currentPosition = transform.GridPosition();
    }

    public void Move(Vector2Int targetPosition)
    {
        Vector3 targetWorldPosition = new Vector3(targetPosition.x, transform.position.y, targetPosition.y);

        transform.LookAt(targetWorldPosition);

        // move from transform.position to targetWorldPosition with movementSpeed
        // notify the caller when done
    }
}

Two things come up:

  • I have to move the object and only want to move if needed, so I don’t want to use Update because it’s just a turn based game
  • I have to notify the caller when the movement is done

First I tried to implement a movement along the grid

public class Movement : MonoBehaviour
{
    [SerializeField]
    float movementSpeed;

    Vector2Int currentPosition;

    void Awake()
    {
        currentPosition = transform.GridPosition();
    }

    IEnumerator Move(Vector2Int targetPosition)
    {
        Vector3 targetWorldPosition = new Vector3(targetPosition.x, transform.position.y, targetPosition.y);

        transform.LookAt(targetWorldPosition);

        while (transform.position != targetWorldPosition)
        {
            transform.position = Vector3.MoveTowards(transform.position, targetWorldPosition, movementSpeed * Time.deltaTime);
            yield return new WaitForEndOfFrame();
        }

        Debug.Log("Notify the caller when done...");
    }
}

I can move objects by calling their movement script

StartCoroutine(movementReference.Move(new Vector2Int(3, 3)));

but how do I notify the calling script that the coroutine has finished?

You can allow passing a delegate as a parameter of the Move method:

IEnumerator Move(Vector2Int targetPosition, System.Action<Movement> onFinished)
{
    Vector3 targetWorldPosition = new Vector3(targetPosition.x, transform.position.y, targetPosition.y);

    transform.LookAt(targetWorldPosition);

    while(transform.position != targetWorldPosition)
    {
        transform.position = Vector3.MoveTowards(transform.position, targetWorldPosition, movementSpeed * Time.deltaTime);
        yield return new WaitForEndOfFrame();
    }

    if(onFinished != null)
    {
        onFinished(this);
    }
}

That’s a great idea :slight_smile:

1 Like