Hold key down for X amount of seconds??How??? C#

Hey,
What i want to do is when you hold down a key for x amount of seconds it wil do something.
And if you released the key before you reached the x amount of seconds it will not do anything.
But how can i Achieve this?

All help is Appreciated!!!

this is what i have but don’t think this is the best way can this be done easier?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    public KeyCode Key;
    public float HoldTime;

    bool StartTimer;

    void Update()
    {
        if (Input.GetKeyDown(Key))
        {
            StartTimer = true;
            StartCoroutine(HoldTimer());
        }

        if (Input.GetKeyUp(Key))
        {
            StartTimer = false;
        }
    }

    IEnumerator HoldTimer()
    {
        Debug.Log("Starting Timer!");
        yield return new WaitForSeconds(HoldTime);
        if(!StartTimer)
        {
            Debug.Log("broke");
        }
        else
            Debug.Log("Timer ENDED!");
    }
}

I believe this should do the trick:

// Warning pseudo code
float startTime = 0f;
float holdTime = 5.0f; // 5 seconds

if GetKeyDown(key)
    startTime = Time.time;
   
if GetKey(key)
    // check if the start time plus [holdTime] is more or equal to the current time.
    // If so, we held the button for [holdTime] seconds.
    if startTime + holdTime >= Time.time;
        DoSomething();

Time.time returns the time since the game started in seconds, by catching the time the moment the button is pressed we get the start of the hold action. By adding the prefered time you want people to hold the button to that and comparing that to the current Time.time value we can see whether 5 seconds has passed.

1 Like

Thnx for the reply
This is what i have now.

But even if the number is 1 or 2 or whatever number it will show the debug.
Did i do something wrong?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    public KeyCode Key;

    public float startTime = 0f;
    public float holdTime = 5.0f; // 5 seconds

    void Update()
    {
        if (Input.GetKey(Key))
        {
            startTime = Time.time;
            if (startTime + holdTime >= Time.time)
                Debug.Log("It Works Great!");
        }
    }
}

I believe input.GetKey gets the key status each frame where as input.GetKeyDown is only true when the key is first pressed so you would need to put startTime = Time.time in an if statement for GetKeyDown.

What @WarmedxMints_1 said.

I also just noticed a mistake in my example, you need to change:

if (startTime + holdTime >= Time.time)

Into:

if (startTime + holdTime <= Time.time)

Because the first case will always return true ^.^

3 Likes

Ah i see
i got it working now thank you so much @WarmedxMints_1 and @Timelog :smile:

Could you maybe post the working code? Even with the change to the inequality sign, the code still doesn’t do what it should.

1 Like

So I figure that this is mostly dead, but here’s the code that I used after reading your replies:

using UnityEngine;

public class KeyboardControls : MonoBehaviour {

    // Timer controls
    private float startTime = 0f;
    private float timer = 0f;
    public float holdTime = 2.0f; // how long you need to hold to trigger the effect

    // Use if you only want to call the method once after holding for the required time
    private bool held = false;

    public string key = "g"; // Whichever key you're using to control the effects. Just hardcode it in if you want
   
    void Update ()
    {
        // Starts the timer from when the key is pressed
        if (Input.GetKeyDown(key))
        {
            startTime = Time.time;
            timer = startTime;
        }

        // Adds time onto the timer so long as the key is pressed
        if (Input.GetKey(key) && held == false)
        {
            timer += Time.deltaTime;

            // Once the timer float has added on the required holdTime, changes the bool (for a single trigger), and calls the function
            if (timer > (startTime + holdTime))
            {
                held = true;
                ButtonHeld();
            }
        }

        // For single effects. Remove if not needed
        if (Input.GetKeyUp(key))
        {
            held = false;
        }
    }

    // Method called after held for required time
    void ButtonHeld()
    {
        Debug.Log("held for " + holdTime + " seconds");
    }
}
8 Likes

Hello, this is an interesting topic. I basically want to know how would I edit my timer and player script to do something similar. My game is taking an input from two push buttons connected to an arduino .
This is the PlayerController script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO.Ports;

public class PlayerController : MonoBehaviour
{
    SerialPort sp = new SerialPort("\\\\.\\COM4", 9600);
    //player = GameObject.FindWithTag("Player").GetComponent<Renderer>().material;

    public float Speed;
    public Vector2 height;
    public float xMin, xMax, yMin, yMax;

    void Awake()
    {
        //player = GameObject.FindWithTag("Player");
    }
    void Start()
    {
        if (!sp.IsOpen)
        { // If the erial port is not open
            sp.Open(); // Open
        }
        sp.ReadTimeout = 1; // Timeout for reading
    }

    public void Update()
    {

        if (sp.IsOpen)
        { // Check to see if the serial port is open
            try
            {

                string value = sp.ReadLine();//To("Button"); //Read the information
                int button = int.Parse(value);
                //float amount = float.Parse(value);
                //transform.Translate(Speed * Time.deltaTime, 0f, 0f);  //walk

                if (button == 0) //*Input.GetKeyDown(KeyCode.Space*/)  //jump
                {
                    GetComponent<Rigidbody2D>().AddForce(height, ForceMode2D.Impulse);
                }
                GetComponent<Rigidbody2D>().position = new Vector3
                (
                    Mathf.Clamp(GetComponent<Rigidbody2D>().position.x, xMin, xMax),
                    Mathf.Clamp(GetComponent<Rigidbody2D>().position.y, yMin, yMax)
                );
            }
            catch (System.Exception)
            {


            }
        }
        void ApplicationQuit()
        {
            if (sp != null)
            {

                {
                    sp.Close();
                }
            }
        }
    }
}

And this is the timer script:

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class Timer : MonoBehaviour
{
   
    public int timeLeft;
    public Text countdownText;

    // Use this for initialization
    void Start()
    {
        StartCoroutine("LoseTime");
       
    }

    // Update is called once per frame
    void Update()
    {
        countdownText.text = ("Time Left = " + timeLeft);

        if (timeLeft <= 0)
        {
            //StopCoroutine("LoseTime");
            //countdownText.text = "Times Up!";
            Invoke("ChangeLevel", 0.1f);
        }
       }

    IEnumerator LoseTime()
    {
        while (true)
        {
            yield return new WaitForSeconds(1);
            timeLeft--;
        }

    }
    void ChangeLevel()
    {

        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    }
}
1 Like

Although this is an old thread, here’s a working code i used to hold button for certain amount of time

//amount of press time=
public float holdThrow=5f;
float holdTimer;

    void Start ()
    {
        holdTimer=holdThrow;
    }

    void Update ()
    {
        if (Input.GetButton("Throw")){
            holdTimer-=Time.deltaTime;
            if(holdTimer<0)
            //function thats being called=
                ThrowItem();
            }
        else
        holdTimer=holdThrow;

    }
2 Likes

THANKS MAN! WORKED GREAT! Very compacted and makes sense!

1 Like