Issue With Input.GetKey and IENumerator in Grabbing Script

So what Im trying to achieve here, is when the player holds down E it continously grabs the item and grabs certain increments per swipe. Now the way I set this up so far, is just to log a string of “Grabbing Item” In this case lets focus on 1 item, a large stack of money. My hope, was when the player is within the colliders of lets say (Money Stack), and if I am holding down E, then every X seconds, the Log should say, “Grabbing Money”.

Now it does do this for sure, but its weird… Lets say we set the EINumerator to yield for about 3 seconds.How its currently playing out, is it waits the 3 seconds but then BOMB! does the log about 20-30 times while im holding down E. If I am to just tap E, it literally does it like 10 times really fast.

Why the heck, is my code playing out this way? My theory is the logic I have for the collider… I think that every split second my player is within the collider, it runs the IENumerator function multiple times within a second. This is the only thing I can think of. But at the same time, I’m not to sure of the proper approach/architecture I should be taking? Any advice is appreciated, thanks.

Code:

public class GrabMoneyStack : MonoBehaviour
{
    // Variables:
    [SerializeField] public int moneyAmt;
    [SerializeField] public float grabSpeed;

    public void OnTriggerStay(Collider other) 
    {
        // check if its the player:
        if(other.tag == "Player")
        {
            // Check to see if user HOLDS DOWN the "E" key:
            if(Input.GetKey(KeyCode.E))
            {
                StartCoroutine(GrabMoney());
            }
        }
    }
    IEnumerator GrabMoney()
    {
        // yield return new WaitForSeconds(Time.deltaTime * grabSpeed);
        yield return new WaitForSeconds(grabSpeed);
        Debug.Log("Grabbed Money!");
    }
}

“I think that every split second my player is within the collider, it runs the IENumerator function multiple times within a second.” Yes, that’s seems to be the problem.

To fix it, just make sure that the coroutine has ended before calling another one.

A simple bool is enough:

public class GrabMoneyStack : MonoBehaviour {
    // Variables:
    [SerializeField] public int moneyAmt;
    [SerializeField] public float grabSpeed;
    private bool grabbingMoney;
    public void OnTriggerStay(Collider other) {
        // check if its the player:
        if (other.tag == "Player") {
            if (Input.GetKey(KeyCode.E) && !grabbingMoney) { // start only is grabbingMoney == false
                StartCoroutine(GrabMoney());
            }
        }
    }
    IEnumerator GrabMoney() {
        grabbingMoney = true;
        yield return new WaitForSeconds(grabSpeed);
        Debug.Log("Grabbed Money!");
        grabbingMoney = false;
    }
}