Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

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

Discussion in 'Scripting' started by Jeremie-de-Vos, Feb 9, 2017.

  1. Jeremie-de-Vos

    Jeremie-de-Vos

    Joined:
    Jun 5, 2015
    Posts:
    120
    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?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Test : MonoBehaviour {
    6.  
    7.     public KeyCode Key;
    8.     public float HoldTime;
    9.  
    10.     bool StartTimer;
    11.  
    12.     void Update()
    13.     {
    14.         if (Input.GetKeyDown(Key))
    15.         {
    16.             StartTimer = true;
    17.             StartCoroutine(HoldTimer());
    18.         }
    19.  
    20.         if (Input.GetKeyUp(Key))
    21.         {
    22.             StartTimer = false;
    23.         }
    24.     }
    25.  
    26.     IEnumerator HoldTimer()
    27.     {
    28.         Debug.Log("Starting Timer!");
    29.         yield return new WaitForSeconds(HoldTime);
    30.         if(!StartTimer)
    31.         {
    32.             Debug.Log("broke");
    33.         }
    34.         else
    35.             Debug.Log("Timer ENDED!");
    36.     }
    37. }
     
  2. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    I believe this should do the trick:
    Code (CSharp):
    1. // Warning pseudo code
    2. float startTime = 0f;
    3. float holdTime = 5.0f; // 5 seconds
    4.  
    5. if GetKeyDown(key)
    6.     startTime = Time.time;
    7.    
    8. if GetKey(key)
    9.     // check if the start time plus [holdTime] is more or equal to the current time.
    10.     // If so, we held the button for [holdTime] seconds.
    11.     if startTime + holdTime >= Time.time;
    12.         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.
     
  3. Jeremie-de-Vos

    Jeremie-de-Vos

    Joined:
    Jun 5, 2015
    Posts:
    120
    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?

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Test : MonoBehaviour {
    6.  
    7.     public KeyCode Key;
    8.  
    9.     public float startTime = 0f;
    10.     public float holdTime = 5.0f; // 5 seconds
    11.  
    12.     void Update()
    13.     {
    14.         if (Input.GetKey(Key))
    15.         {
    16.             startTime = Time.time;
    17.             if (startTime + holdTime >= Time.time)
    18.                 Debug.Log("It Works Great!");
    19.         }
    20.     }
    21. }
     
  4. WarmedxMints

    WarmedxMints

    Joined:
    Feb 6, 2017
    Posts:
    739
    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.
     
  5. Timelog

    Timelog

    Joined:
    Nov 22, 2014
    Posts:
    528
    What @WarmedxMints said.

    I also just noticed a mistake in my example, you need to change:
    Code (CSharp):
    1. if (startTime + holdTime >= Time.time)
    Into:
    Code (CSharp):
    1. if (startTime + holdTime <= Time.time)
    Because the first case will always return true ^.^
     
    Martin_09 and Jeremie-de-Vos like this.
  6. Jeremie-de-Vos

    Jeremie-de-Vos

    Joined:
    Jun 5, 2015
    Posts:
    120
    Ah i see
    i got it working now thank you so much @WarmedxMints and @Timelog :D
     
  7. noah_petro

    noah_petro

    Joined:
    Jun 20, 2017
    Posts:
    6
    Could you maybe post the working code? Even with the change to the inequality sign, the code still doesn't do what it should.
     
  8. unity_NHlmm2QPJRKl0g

    unity_NHlmm2QPJRKl0g

    Joined:
    Apr 23, 2018
    Posts:
    1
    So I figure that this is mostly dead, but here's the code that I used after reading your replies:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class KeyboardControls : MonoBehaviour {
    4.  
    5.     // Timer controls
    6.     private float startTime = 0f;
    7.     private float timer = 0f;
    8.     public float holdTime = 2.0f; // how long you need to hold to trigger the effect
    9.  
    10.     // Use if you only want to call the method once after holding for the required time
    11.     private bool held = false;
    12.  
    13.     public string key = "g"; // Whichever key you're using to control the effects. Just hardcode it in if you want
    14.    
    15.     void Update ()
    16.     {
    17.         // Starts the timer from when the key is pressed
    18.         if (Input.GetKeyDown(key))
    19.         {
    20.             startTime = Time.time;
    21.             timer = startTime;
    22.         }
    23.  
    24.         // Adds time onto the timer so long as the key is pressed
    25.         if (Input.GetKey(key) && held == false)
    26.         {
    27.             timer += Time.deltaTime;
    28.  
    29.             // Once the timer float has added on the required holdTime, changes the bool (for a single trigger), and calls the function
    30.             if (timer > (startTime + holdTime))
    31.             {
    32.                 held = true;
    33.                 ButtonHeld();
    34.             }
    35.         }
    36.  
    37.         // For single effects. Remove if not needed
    38.         if (Input.GetKeyUp(key))
    39.         {
    40.             held = false;
    41.         }
    42.     }
    43.  
    44.     // Method called after held for required time
    45.     void ButtonHeld()
    46.     {
    47.         Debug.Log("held for " + holdTime + " seconds");
    48.     }
    49. }
     
  9. Grey_Wolf9

    Grey_Wolf9

    Joined:
    Jul 30, 2018
    Posts:
    1
    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:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.IO.Ports;
    5.  
    6. public class PlayerController : MonoBehaviour
    7. {
    8.     SerialPort sp = new SerialPort("\\\\.\\COM4", 9600);
    9.     //player = GameObject.FindWithTag("Player").GetComponent<Renderer>().material;
    10.  
    11.     public float Speed;
    12.     public Vector2 height;
    13.     public float xMin, xMax, yMin, yMax;
    14.  
    15.     void Awake()
    16.     {
    17.         //player = GameObject.FindWithTag("Player");
    18.     }
    19.     void Start()
    20.     {
    21.         if (!sp.IsOpen)
    22.         { // If the erial port is not open
    23.             sp.Open(); // Open
    24.         }
    25.         sp.ReadTimeout = 1; // Timeout for reading
    26.     }
    27.  
    28.     public void Update()
    29.     {
    30.  
    31.         if (sp.IsOpen)
    32.         { // Check to see if the serial port is open
    33.             try
    34.             {
    35.  
    36.                 string value = sp.ReadLine();//To("Button"); //Read the information
    37.                 int button = int.Parse(value);
    38.                 //float amount = float.Parse(value);
    39.                 //transform.Translate(Speed * Time.deltaTime, 0f, 0f);  //walk
    40.  
    41.                 if (button == 0) //*Input.GetKeyDown(KeyCode.Space*/)  //jump
    42.                 {
    43.                     GetComponent<Rigidbody2D>().AddForce(height, ForceMode2D.Impulse);
    44.                 }
    45.                 GetComponent<Rigidbody2D>().position = new Vector3
    46.                 (
    47.                     Mathf.Clamp(GetComponent<Rigidbody2D>().position.x, xMin, xMax),
    48.                     Mathf.Clamp(GetComponent<Rigidbody2D>().position.y, yMin, yMax)
    49.                 );
    50.             }
    51.             catch (System.Exception)
    52.             {
    53.  
    54.  
    55.             }
    56.         }
    57.         void ApplicationQuit()
    58.         {
    59.             if (sp != null)
    60.             {
    61.  
    62.                 {
    63.                     sp.Close();
    64.                 }
    65.             }
    66.         }
    67.     }
    68. }
    69.  
    70.  
    71.  
    And this is the timer script:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class Timer : MonoBehaviour
    7. {
    8.    
    9.     public int timeLeft;
    10.     public Text countdownText;
    11.  
    12.     // Use this for initialization
    13.     void Start()
    14.     {
    15.         StartCoroutine("LoseTime");
    16.        
    17.     }
    18.  
    19.     // Update is called once per frame
    20.     void Update()
    21.     {
    22.         countdownText.text = ("Time Left = " + timeLeft);
    23.  
    24.         if (timeLeft <= 0)
    25.         {
    26.             //StopCoroutine("LoseTime");
    27.             //countdownText.text = "Times Up!";
    28.             Invoke("ChangeLevel", 0.1f);
    29.         }
    30.        }
    31.  
    32.     IEnumerator LoseTime()
    33.     {
    34.         while (true)
    35.         {
    36.             yield return new WaitForSeconds(1);
    37.             timeLeft--;
    38.         }
    39.  
    40.     }
    41.     void ChangeLevel()
    42.     {
    43.  
    44.         SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
    45.     }
    46. }