3

How to make button press function work only in between # seconds? For example, allow user to press E at any time, but execute, for example, animation every 5 seconds? I've tried Invoke but it doesnt seem to work as it should. I've also tried timestamp and StartCoroutine (waitforseconds).

Here's what I got so you can see:

    void Update()
{
        if (triggerIsOn && Input.GetKeyDown(KeyCode.E))
    {
        drinkAmin.Play("DrinkVodka");
        StartCoroutine(letsWait());

    }
}

And

IEnumerator letsWait(){

        Debug.Log ("lets wait works!");
        yield return new WaitForSeconds (5);
        TakeAshot ();
    }

It all works, but not by 5 seconds in between, but rather it works every 5 seconds after each button press. So, this doesn't work as it should. Can anyone help me? A bit lost here. Thanks!

papi
  • 379
  • 7
  • 25
  • Would it be easier to detach the event at animation's starts and reattach it after 5 seconds has been elapsed? – KMC Dec 27 '17 at 07:40
  • That might work, but it doesnt seem to be a wise thing to do? @KMC – papi Dec 29 '17 at 05:31

2 Answers2

2

I came up with a solution for debouncing input events in Unity by using coroutines and unique identifiers for each coroutine call.

public class Behaviour : MonoBehaviour
{
    private Guid Latest;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.E))
        {
            // start the debounced input handler coroutine here
            StartCoroutine(Debounced());
        }
    }

    private IEnumerator Debounced()
    {
        // generate a new id and set it as the latest one 
        var guid = Guid.NewGuid();
        Latest = guide;

        // set the denounce duration here
        yield return new WaitForSeconds(3);

        // check if this call is still the latest one
        if (Latest == guid)
        {
             // place your debounced input handler code here
        }
    }
}

What this code does is generates a unique id for each call of the Debounced method and sets the id of the latest Debounced call. If the latest call id matches the current call id then the code is executed. Otherwise, another call happened before this one so we don't run the code for that one.

The Guid class is in the System namespace so you will need to add a using statement at the top of the file: using System;.

MKrup
  • 231
  • 4
  • 6
  • Very useful. For UI elements using an `onValueChanged` listener, you can get away with not using the guid, but checking the value returned by the event instead – Felipe Oct 27 '21 at 16:17
  • Doesn't this code wait 3 seconds to execute even if the key is only pressed once? That can't be intended.. – Hockenmaier Sep 07 '22 at 16:15
1

What you're talking about is called a 'debouncer'. There's a good SO question about this already: C# event debounce - try using one of the approaches there.

Dan Schnau
  • 1,505
  • 14
  • 17
  • I've tried a few debounce implementations including my own, and it seems like unity does not handle UI on separate threads – Felipe Oct 27 '21 at 14:56