Search Unity

Better ways to detect double click

Discussion in 'Scripting' started by ofek_, Mar 29, 2014.

  1. ofek_

    ofek_

    Joined:
    Mar 15, 2014
    Posts:
    18
    I just started to program new controller for a character and i have huge problem.
    I want the code to detect double click from my left and right arrow keys, Its the first time i ever programed double click detection and i want to see if there is any better way for doing so (I'm sure there is).
    When the player pressed twice on the same arrow key it dash to that derection.

    I started with a really simple code but he just to long and i really need to optmize it.

    The double click detection part is betwenn 52 to 80.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class characterController : MonoBehaviour {
    6.  
    7.     public int dashSpeed = 20;
    8.     private int movementSpeed = 10;
    9.  
    10.     //animatoer refernces
    11.     private Animator anim;
    12.     private AnimatorStateInfo animBaseState;
    13.  
    14.     private bool facingRight = true;
    15.  
    16.     //double click detection variables
    17.     private bool sameKeyDetection = true; //Separating between left and right
    18.     private bool firstKeyPressed = false;
    19.     private float timeForNextKey = 0.15f;
    20.     private float doubleClickTimer = -2;
    21.     private float falseTimer = -2;
    22.  
    23.  
    24.  
    25.     static int dashState = Animator.StringToHash("Base Layer.Dash");
    26.  
    27.     //flip the charcter sprite when pressing the negative derection.
    28.     void Flip(){
    29.         facingRight = !facingRight;
    30.         Vector3 theScale = transform.localScale;
    31.         theScale.x *= -1;
    32.         transform.localScale = theScale;
    33.     }
    34.  
    35.  
    36.     // Use this for initialization
    37.     void Start () {
    38.         anim = gameObject.GetComponent<Animator> ();
    39.     }
    40.    
    41.     // Update is called once per frame
    42.     void Update () {
    43.         animBaseState = anim.GetCurrentAnimatorStateInfo (0);
    44.  
    45.         //input setting
    46.         float velocity = Input.GetAxis ("Horizontal");
    47.         bool right = Input.GetButtonDown ("Right");
    48.         bool left = Input.GetButtonDown ("Left");
    49.         //animator parameters
    50.         anim.SetFloat ("Speed", Mathf.Abs (velocity));
    51.        
    52.  
    53.         if (right  firstKeyPressed  sameKeyDetection){
    54.             anim.SetBool("Dash", true);
    55.             firstKeyPressed = false;        //if the player pressed RIGHT for rhe secound time
    56.             falseTimer = Time.time;
    57.         }
    58.         else if(left  firstKeyPressed  !sameKeyDetection){
    59.             anim.SetBool("Dash", true);     //if the player pressed LEFT for rhe secound time
    60.             firstKeyPressed = false;       
    61.             falseTimer = Time.time;
    62.         }
    63.         else if (right){
    64.             sameKeyDetection = true;        //if the player pressed RIGHT for the first time
    65.             firstKeyPressed = true;        
    66.             doubleClickTimer = Time.time;
    67.         }
    68.         else if(left){
    69.             sameKeyDetection = false;       ///if the player pressed LEFT for the first time
    70.             firstKeyPressed = true;
    71.             doubleClickTimer = Time.time;
    72.         }
    73.  
    74.         if(Time.time - doubleClickTimer > timeForNextKey){
    75.             firstKeyPressed = false;        //after 0.15 secound (timeForNextKey) it resets the input
    76.         }                                   // the player need to press twice on the same derection to
    77.                                             //dash within 0.15 sec
    78.  
    79.         if(Time.time - falseTimer > 0.3){   // I added that timer because
    80.             anim.SetBool("Dash", false);    // the animator didnt responded to 1 fram input    
    81.         }
    82.  
    83.  
    84.  
    85.         //after detecting double click that part sould make the charcter dash
    86.         //(there is simple movement in here as well)
    87.         //dont have any porblems with that part.
    88.         if (animBaseState.nameHash != dashState){
    89.             transform.Translate (Vector2.right * velocity * Time.deltaTime * movementSpeed);
    90.             if (velocity > 0  !facingRight)
    91.                 Flip();
    92.        
    93.             else if (velocity < 0  facingRight)
    94.                 Flip();
    95.         }
    96.         else if (animBaseState.nameHash == dashState){
    97.             if (facingRight)
    98.                 transform.Translate(Vector2.right*dashSpeed*Time.deltaTime);
    99.             else
    100.                 transform.Translate(-Vector2.right*dashSpeed*Time.deltaTime);
    101.         }
    102.     }
    103. }
    104.  

    Hope you could help me find defrent approach to solve this problem.
    Thanks in advance
     
  2. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    Your code isn't all that long tbh, but you could clean your code up a little by making a function to detect the double press. I must warn you that I have not tested this source code, but it *should* work. Let me know if you get stuck and I will try my best to help :)

    Utility class to make code inside your behaviour cleaner:
    This class should help you to detect double, triple, etc clicks :)
    Code (csharp):
    1.  
    2. public static class MultiClickInput {
    3.  
    4.     // Default time in seconds for which to detect double clicking of a key.
    5.     public const float DefaultTimeThreshold = 0.5f;
    6.  
    7.     private static string _multiClickAnchorKey;
    8.     private static float _multiClickAnchorTime;
    9.     private static int _multiClickCount;
    10.  
    11.     public static void CancelMultiClick() {
    12.         _multiClickAnchorKey = null;
    13.     }
    14.  
    15.     public static int GetMultiClickKeyCount(string key, float timeThreshold) {
    16.         if (Input.GetButtonDown(key)) {
    17.             // Do we need to cancel the last multi-click operation for this key?
    18.             if (_multiClickAnchorKey == key)
    19.                 if (Time.time - _multiClickAnchorTime > timeThreshold)
    20.                     CancelMultiClick();
    21.  
    22.             _multiClickAnchorTime = Time.time;
    23.  
    24.             // Has button been pressed for first time?
    25.             if (_multiClickAnchorKey != key) {
    26.                 _multiClickAnchorKey = key;
    27.                 _multiClickCount = 1;
    28.             }
    29.             else {
    30.                 // Okay, so this is a multi-click operation!
    31.                 ++_multiClickCount;
    32.             }
    33.             return _multiClickCount;
    34.         }
    35.         return 0;
    36.     }
    37.  
    38.     public static int GetMultiClickKeyCount(string key) {
    39.         return GetMultiClickKeyCount(key, DefaultTimeThreshold);
    40.     }
    41.  
    42.     public static bool HasDoubleClickedKey(string key, float timeThreshold) {
    43.         return GetMultiClickKeyCount(key, timeThreshold) == 2;
    44.     }
    45.  
    46.     public static bool HasDoubleClickedKey(string key) {
    47.         return HasDoubleClickedKey(key, DefaultTimeThreshold);
    48.     }
    49.  
    50. }
    51.  
    Usage Example:
    I wasn't quite sure what you were using the `falseTimer` variable for, so I have left that out.
    Code (csharp):
    1.  
    2. using UnityEngine;
    3.  
    4. using System.Collections;
    5.  
    6. public class characterController : MonoBehaviour {
    7.  
    8.     public int dashSpeed = 20;
    9.     private int movementSpeed = 10;
    10.  
    11.     //animatoer refernces
    12.     private Animator anim;
    13.     private AnimatorStateInfo animBaseState;
    14.  
    15.     private bool facingRight = true;
    16.  
    17.     //double click detection variables
    18.     private float timeForNextKey = 0.15f;
    19.  
    20.     static int dashState = Animator.StringToHash("Base Layer.Dash");
    21.  
    22.     //flip the charcter sprite when pressing the negative derection.
    23.     void Flip(){
    24.         facingRight = !facingRight;
    25.         Vector3 theScale = transform.localScale;
    26.         theScale.x *= -1;
    27.         transform.localScale = theScale;
    28.     }
    29.  
    30.     // Use this for initialization
    31.     void Start () {
    32.         anim = gameObject.GetComponent<Animator> ();
    33.     }
    34.  
    35.     // Update is called once per frame
    36.     void Update () {
    37.         animBaseState = anim.GetCurrentAnimatorStateInfo (0);
    38.  
    39.         //input setting
    40.         float velocity = Input.GetAxis ("Horizontal");
    41.         //animator parameters
    42.         anim.SetFloat ("Speed", Mathf.Abs (velocity));
    43.  
    44.  
    45.         if (MultiClickInput.HasDoubleClickedKey("Right", timeForNextKey)) {
    46.             anim.SetBool("Dash", true);
    47.         }
    48.         else if (MultiClickInput.HasDoubleClickedKey("Left", timeForNextKey)) {
    49.             anim.SetBool("Dash", true);
    50.         }
    51.  
    52.  
    53.         //after detecting double click that part sould make the charcter dash
    54.         //(there is simple movement in here as well)
    55.         //dont have any porblems with that part.
    56.         if (animBaseState.nameHash != dashState){
    57.             transform.Translate (Vector2.right * velocity * Time.deltaTime * movementSpeed);
    58.             if (velocity > 0  !facingRight)
    59.                 Flip();
    60.  
    61.             else if (velocity < 0  facingRight)
    62.                 Flip();
    63.         }
    64.         else if (animBaseState.nameHash == dashState){
    65.             if (facingRight)
    66.                 transform.Translate(Vector2.right*dashSpeed*Time.deltaTime);
    67.             else
    68.                 transform.Translate(-Vector2.right*dashSpeed*Time.deltaTime);
    69.         }
    70.     }
    71. }
    72.  
    I hope that this helps for you :)
     
    Last edited: Mar 30, 2014