IEnumerator doesn't break even when I use yield break


The idea of the game is to have the left car move between the two nodes(Pink Diamonds) on the left side of the grid and to have the right car do the same on the right side. I am using an IEnumerator that begins when either the "left arrow" or "a" is pressed and it lerps the car from its current position to the next node. Same for the right side but with "right arrow" and "d". The cars lerp like they are supposed to and go to their destination. The problem is that I want to make it so that even if it’s in the middle of a car moving if you press the button again it starts heading towards the other node. So technically if you wanted you could spam the key and it would wobble around the middle. I tried to use a boolean called leftClicked to tell the IEnumerator to break every time a new button is pressed because I start a new IEnumerator lerping towards the next node but the car continuous to its end path and the second it gets there it then teleports to where the current new IEnumerator is at in the lerping process, the IEnumerator that I started when I pressed the key for a second time before.
Here’s the code:

public class OneMoreMovement : MonoBehaviour
{

    public GameObject[] leftNode; 
    //contains both nodes on the left side of the grid
    public GameObject[] rightNode; 
    //contains both nodes on the right side of the grid
    public GameObject[] car; 
    //car[0] is the left car and car[1] is the right

    int L = 1; 
    int R = 1; //current left and right node states| these tell the cars the next node to go to when it starts lerping | L is for the left nodes and R for the right

    Vector3 currentPosLeft;
    Vector3 currentPosRight;
    public float desiredMovementTime;
    bool leftClicked = false;
    bool rightClicked = false;


    // Start is called before the first frame update
    void Start()
    {
        currentPosLeft = car[0].transform.position;
        currentPosRight = car[1].transform.position;
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.A))
        {
            leftClicked = true;
            StartCoroutine(MoveLeft(desiredMovementTime));
        }
        if (Input.GetKeyUp(KeyCode.RightArrow) || Input.GetKeyUp(KeyCode.D))
        {
            rightClicked = true;
            StartCoroutine(MoveRight(desiredMovementTime));
        }

    }
    private IEnumerator MoveLeft(float desiredTime)
    {
        leftClicked = false;
        float elapsedTime = 0;

        while (elapsedTime < desiredTime)
        {
            yield return null;
            if (leftClicked) { break; }
            elapsedTime += Time.deltaTime;
            float percentageComplete = elapsedTime / desiredTime;

            car[0].transform.position = Vector3.Lerp(currentPosLeft, leftNode[L].transform.position, percentageComplete);
        }

        if (L == 1) { L = 0; }
        else { L = 1; }
        currentPosLeft = car[0].transform.position;
    }
    private IEnumerator MoveRight(float desiredTime)
    {
        rightClicked = false;
        float elapsedTime = 0;

        while (elapsedTime < desiredTime)
        {
            yield return null;
            if (rightClicked) { yield break; }
            elapsedTime += Time.deltaTime;
            float percentageComplete = elapsedTime / desiredTime;

            car[1].transform.position = Vector3.Lerp(currentPosRight, rightNode[R].transform.position, percentageComplete);
        }

        if (R == 1) { R = 0; }
        else { R = 1; }
        currentPosRight = car[1].transform.position;
    }
}

Is there something I am missing or am I just vastly misinterpreting the use of IEnumerator?

Not entierly sure here about the context of IEnumerator.
I think the problem is that your IEnumerator function encapsulates the variable rightClicked and it wont update after in the normal update because IEnumerator is executed elsewhere?

Anyway you need to save the coroutine and stop the coroutine in your update function instead of changing a flag and stopping the coroutine from the inside:

You are setting your leftClicked and rightClicked flags then immediately starting a coroutine that sets them back. The flag is never seen by the active coroutine you are trying to stop. You are in essence spawning many coroutines without stopping them, causing the buggy behavior. As @Hawaii_Dev said, you could stop the coroutine with StopCoroutine, as this would probably be a cleaner way of accomplishing what you are aiming for.

Thanks a bunch guys. I didn’t know about each coroutine being its on individual event basically given an identifier each time one is created and if you manage that identifier instead of the method you can start and stop it on command. Anyways I read a bunch of notation on Coroutines and figured it out. Here is the final result that got it working. I used the string Coroutine method because when it stops it doesnt resume from where it left when it starts again rather it restarts the movement from the new inputed spots.

public class OneMoreMovement : MonoBehaviour
{

public GameObject[] leftNode; 
//contains both nodes on the left side of the grid
public GameObject[] rightNode; 
//contains both nodes on the right side of the grid
public GameObject[] car; 
//car[0] is the left car and car[1] is the right

int L = 1; 
int R = 1; //current left and right node states| these tell the cars the next node to go to when it starts lerping | L is for the left nodes and R for the right

Vector3 currentPosLeft;
Vector3 currentPosRight;
public float desiredMovementTime;

// Start is called before the first frame update
void Start()
{
    
}

// Update is called once per frame
void Update()
{
    if (Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.A))
    {
        if ("MoveLeft" != null) { StopCoroutine("MoveLeft"); }
        StartCoroutine("MoveLeft", desiredMovementTime);
    }
    if (Input.GetKeyUp(KeyCode.RightArrow) || Input.GetKeyUp(KeyCode.D))
    {
        if ("MoveRight" != null) { StopCoroutine("MoveRight"); }
        StartCoroutine("MoveRight", desiredMovementTime);
    }

}

private IEnumerator MoveLeft(float desiredTime)
{
    if (L == 1) { L = 0; } //moved because otherwise you might end Coroutine before it plays into effect
    else { L = 1; }
    currentPosLeft = car[0].transform.position; //moved because car would start at original position never came into effect

    float elapsedTime = 0;

    while (elapsedTime < desiredTime)
    {
        yield return null;
        
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredTime;

        car[0].transform.position = Vector3.Lerp(currentPosLeft, leftNode[L].transform.position, percentageComplete);
    }

    
    currentPosLeft = car[0].transform.position;
}
private IEnumerator MoveRight(float desiredTime)
{
    if (R == 1) { R = 0; }
    else { R = 1; }
    currentPosRight = car[1].transform.position;

    float elapsedTime = 0;

    while (elapsedTime < desiredTime)
    {
        yield return null;
        
        elapsedTime += Time.deltaTime;
        float percentageComplete = elapsedTime / desiredTime;

        car[1].transform.position = Vector3.Lerp(currentPosRight, rightNode[R].transform.position, percentageComplete);
    }
    
    currentPosRight = car[1].transform.position;
}

}