Search Unity

Double Tapping axis input

Discussion in 'Scripting' started by christchild, Feb 1, 2008.

  1. christchild

    christchild

    Joined:
    Jun 12, 2007
    Posts:
    30
    Hi,

    I am trying to code a double tap input with Js. I Hope that it will change a "walk" animation into a "jump forward" animation.
    It seems to work once and then its results become erratic.

    What am I doing wrong?
    or
    Is there a better way to do this?

    (Note: I've remove any animation code to keep it simple. You can attach this code to a empty game object to see what happens)

    Code (csharp):
    1.  
    2. var fwd : float = 0;
    3. var DoubleTapFwd : float = 0;
    4.  
    5.  
    6. function Update() {
    7.     var Horizontal : float = Input.GetAxisRaw ("Horizontal");
    8.    
    9. // reset fwd to 0 if there's no input.
    10.     if (Horizontal == 0)    {
    11.         // ^^ Idle animation Here
    12.         fwd = fwd - fwd;
    13.         }
    14.  
    15.     if (Horizontal > 0) {
    16.         // ^^ walk animation Here
    17.         mover();
    18.         }
    19.  
    20. // Should reset DoubleTapFwd to 0  
    21.     if (DoubleTapFwd == 2){
    22.         // ^^ jump forward animation Here
    23.         }
    24.    
    25.    
    26.     if (DoubleTapFwd > 2) {
    27.         DoubleTapFwd = DoubleTapFwd - DoubleTapFwd;
    28.         }
    29. // print input results.
    30. print(" fwd = "+fwd + "  DoubleTapFwd =" + DoubleTapFwd);
    31. }
    32.  
    33. //every time fwd is pressed fwd increases when you let go fwd is set to 0
    34. function mover(){
    35. var Horizontal : float = Input.GetAxisRaw ("Horizontal");
    36.        
    37.             if (Horizontal == 1){
    38.             fwd += 1;
    39.             }
    40.            
    41.             //every time fwd = 3 one is added to Doubletap
    42.             if (fwd == 3){
    43.             DoubleTapFwd += 1;
    44.             }
    45. }
    46.  
    P.S. as you can see I'm a javascript n00b!
     
  2. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    The easiest way to do this is for you just to download my project file.

    "oldOne" is your code with some of my comments included. My words are in brackets, in the comments.

    "newOne" is a recreated version that I think will work out a lot better for you. It is commented out to prevent errors due to no animations being present in the project. Select All and hit Command-/ to un-comment with Unitron (available as a command in the Text menu as well).

    Finally, "noAnims" is similar code that requires no animations to be present in order to work. Just watch the words that are generated by the print() function. This is the script that is running in the "test scene".

    Thanks very much to Eric for initially helping me figure out how to do double-clicks / double-taps back when I started programming last year:

    http://forum.unity3d.com/viewtopic.php?t=5948&highlight=

    Here is one cool and perhaps not immediately obvious thing that should happen using my code: if you hold forward down the entire time of the lunge, or if you just end up holding it at the end of it, you will continue walking as soon as the lunge animation is done, without having to wait or anything. That should make for more fun, responsive gameplay. Not that this behavior isn't standard...it's just something I wanted to make sure was included.

    Anyway, let me know how all of this works out for you. Good luck!
     

    Attached Files:

  3. christchild

    christchild

    Joined:
    Jun 12, 2007
    Posts:
    30
    Thanks Jessy, I going to give it a try right now. I'll post how I got on.

    ...

    O.k. I tried it, works perfectly, ten-thousands thank you's to you jessy.
    You also took the time to correct my code and every thing you have commented
    has made it easy for me to understand.
    If your ever in Ireland I owe you a pint!
     
  4. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Any luck?

    ...I see the edit now! Glad to hear it!
     
  5. teatime

    teatime

    Joined:
    Jun 16, 2008
    Posts:
    129
    thanks for this, jessy, i wanted to implement a double-tap-and-hold run ability like in a kirby or smash bros game and i modified your code to get this:

    Code (csharp):
    1.  
    2.  
    3.                 // disable double-tapping after a short time limit 
    4.                 if (Time.time > lastTapFwdTime + dblTapFwdTime)
    5.                 {
    6.                     dblTapFwdReady = false;
    7.                 }
    8.                
    9.  
    10.                     if (verticalraw == 1) {
    11.                        
    12.                             lastTapFwdTime = Time.time;
    13.                             if (dblTapFwdReady)
    14.                                 {basicForwardSpeed = 1.5f;
    15.                                 maxForwardAccel = 1f;
    16.                                     print ("running");}
    17.                                     else {
    18.                                         print ("walking");
    19.                                         basicForwardSpeed = 0.5f;
    20.                                         maxForwardAccel = 0.75f;}
    21.  
    22.                     }
    23.                     else {dblTapFwdReady = true;}
    24.  
    25.                     if (verticalraw == 0) {
    26.                         // ^^ Idle animation Here
    27.                         print ("relaxing");
    28.                     }
    the only problem i'm having is that when the framerate drops momentarily it loses the double-tap and goes back to walking. is there any way to prevent this, or is it an inevitable side-effect of a framerate stutter?

    in addition to the running, i want to be able to double-tap either to the left or right and have the character controller do a "dodge" move in the appropriate direction. what's the best way to go about moving it a set length on the x axis over a specified period of time, with more speed at the beginning of the move and a short pause at the end?
     
  6. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I think this code will solve your problems and be more efficient that what I posted before:

    Code (csharp):
    1. var doubleTapToRunTime : float;  // Tap twice within this time and you will be running.
    2.  
    3. private var moving = false;
    4. private var tapFwdToRun = false;  // whether you you will start running upon the next tap
    5. private var lastTapFwdTime : float;  // the time of the last tap that occurred
    6.  
    7. function Update ()
    8. {      
    9.     var verticalRaw = Input.GetAxisRaw("Vertical");
    10.    
    11.     if (moving  verticalRaw == 0)
    12.     {
    13.         Debug.Log("not moving");
    14.         moving = false;
    15.         if (Time.time > lastTapFwdTime + doubleTapToRunTime)
    16.             tapFwdToRun = false;
    17.     }
    18.  
    19.     else if (!moving  verticalRaw == 1)
    20.     {    
    21.         if (tapFwdToRun)
    22.         {
    23.             Debug.Log("running");
    24.             tapFwdToRun = false;
    25.         }
    26.         else
    27.         {
    28.             Debug.Log("walking");
    29.             tapFwdToRun = true;
    30.             lastTapFwdTime = Time.time;
    31.         }
    32.         moving = true;
    33.     }          
    34. }
    Do keep in mind that this is really only suited for digital control. Double-tapping an analog stick to its limits is a pain. That's why Smash Bros. bases its running mechanism on how fast you tilt the stick, unless you're playing with the Wii Remote by itself (which I don't recommend).

    As for your question about the dodge, I wouldn't try to code that kind of movement. You'd be better off triggering a dodge animation which you create in a 3D animation package.

    Good luck, and let me know how this new code works out for you.
     
  7. teatime

    teatime

    Joined:
    Jun 16, 2008
    Posts:
    129
    yeah, i'm only expecting this game to be played with wasd + mouse. the idea behind the double-tap run was to give digital control a little more nuance in motion without increasing the number of buttons.

    i actually kind of liked the way the old code counted holding the key as a tap, because you could go from walk to run faster with less effort. but this code will be a lot easier to read later on and if it solves the problem i had before (i tested it for a while, but i didn't seem to have another significant frame-rate dip) it might be worth the trade-off.

    i should probably finally bite the bullet and start learning 3d animation. will translation determined by animation be constrained by collisions? and am i right in assuming that the animation that moves the character controller capsule should be separate from the animation that drives the character model's movements, and that the latter should not deviate from center for the purposes of movement?
     
  8. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Try this instead then:
    Code (csharp):
    1. var tapAgainToRunTime : float;
    2.  
    3. private var moving = false;
    4. private var walking = false;
    5. private var latestWalkRestTime : float;
    6.  
    7. function Update ()
    8. {
    9.     var verticalRaw = Input.GetAxisRaw("Vertical");
    10.    
    11.     if (moving  verticalRaw == 0)
    12.     {
    13.         Debug.Log("not moving");
    14.         moving = false;
    15.         if (walking)
    16.         {
    17.             latestWalkRestTime = Time.time;
    18.             walking = false;
    19.         }
    20.     }
    21.          
    22.     else if (!moving  verticalRaw == 1)
    23.     {      
    24.         if (Time.time < latestWalkRestTime + tapAgainToRunTime)
    25.             Debug.Log("running");
    26.         else
    27.         {
    28.             Debug.Log("walking");
    29.             walking = true;
    30.         }
    31.         moving = true;
    32.     }          
    33. }
    Ug, this really is a pain. You seem to be right on the animation not being constrained front. The colliders move with the animated objects, though. I don't have any good advice about how to make this easy on you. Perhaps you can start a new topic devoted specifically to this, because I'd like to know myself.
     
  9. teatime

    teatime

    Joined:
    Jun 16, 2008
    Posts:
    129
    awesome. thanks so much jessy.

    seems like animation should be constrained simply by checking "animate physics," and yet there's this thread:
    http://forum.unity3d.com/viewtopic.php?t=13877

    so i have no idea what to think. will have to do some research.
     
  10. olecalfheim

    olecalfheim

    Joined:
    Aug 27, 2010
    Posts:
    3
    Thank you so much for sharing the script! But..

    I got this code working with the 2D PlatformerController.js script, but it only seems to be working when running RIGHT, and not LEFT. I downloaded the example project, and the issue seems to be present there as well. What I'm missing?

    Thanks!
     
  11. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
  12. agirardi24

    agirardi24

    Joined:
    Sep 13, 2010
    Posts:
    12
    Jessy your insight has been helpful and I thank you for sharing. If I could ask for a little more, needing to double tap to dash I'm using a slightly modified version of your Sun Aug 02, 2009 8:57 am code. It does what I need it to do, but it cuts my movement speed to a crawl. I would appreciate the help if you can.

    Code (csharp):
    1.  
    2. if (moving  horizontalDirection == 0)
    3. {
    4.     moving = false;
    5.     if (Time.time > lastTapTime + doubleTapToRunTime)
    6.     {
    7.          tapFwdToRun = false;
    8.     }
    9. }
    10. else if (!moving  horizontalDirection == 1)
    11. {      
    12.     if (tapFwdToRun)
    13.     {
    14.         tapFwdToRun = false;
    15.         horizontalDirection *= dashSpeed;
    16.     }
    17.     else
    18.     {
    19.          tapFwdToRun = true;
    20.          lastTapTime = Time.time;
    21.          horizontalDirection *= fowardSpeed;
    22.     }
    23.         moving = true;
    24. }
    25. else if (!moving  horizontalDirection == -1)
    26. {      
    27.     if (tapBckToRun)
    28.     {
    29.         tapBckToRun = false;
    30.         horizontalDirection *= dashSpeed;
    31.     }
    32.    else
    33.     {
    34.         tapBckToRun = true;
    35.         lastTapTime = Time.time;
    36.         horizontalDirection *= fowardSpeed;
    37.     }
    38.         moving = true;
    39. }
    40.  
     
  13. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Let's see more of that code. I don't know what horizontalDirection is, especially how it's triggered.
     
  14. agirardi24

    agirardi24

    Joined:
    Sep 13, 2010
    Posts:
    12
    horizontalDirection = Input.GetAxisRaw(horizontalAxis);
     
  15. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    The code is overcomplicated. Please tell me exactly the behavior you want. Also, please tell me if you can use C#. The code will be less messy and easier to read, with the ability to use Properties, but UnityScript doesn't have them, as far as I know.
     
  16. agirardi24

    agirardi24

    Joined:
    Sep 13, 2010
    Posts:
    12
    What I was looking for was if you just hold the button down to just walk normally. But when you double tap the character dashes forward. I am using c# but I was not using properties.
     
  17. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I'm not sure what these mean to you. Here is the simplest possible case I can think of, though. Hopefully it's easier to follow than what you posted, so you can glean what you need to from it. There are a couple caveats with this:

    • It doesn't account for releasing and pressing the same direction before the next frame, nor do I have any clue how you'd handle that. Shouldn't be a problem for anybody but this guy, though. :wink: Superhumans like that could use the fact that you can tap in one direction, and then the opposite, to run, however. (Of course, this has to happen over the course of a frame, but one frame should take half the time of two!)
    • Like I said last year, it won't work with an analog stick, but double-smashing with an analog stick is a horrible input mechanism and I don't support it. :p
     

    Attached Files:

  18. agirardi24

    agirardi24

    Joined:
    Sep 13, 2010
    Posts:
    12
    Your fix didn't work strangely, when I change the first if (moving horizontalDirection == 0) to just an else. It works but the character dashes and never walks. I'm going to send my control scrip and the build so you can see. It's not pretty but It's been doing what it needs to do until now
     

    Attached Files:

  19. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    That's because you didn't reset it.

    Your script is too long for me to try to make sense of. Again, try my script on a game object you can see moving (reset it this time so it actually works), make sure you understand it; ask specific questions if you have them.
     

    Attached Files:

  20. agirardi24

    agirardi24

    Joined:
    Sep 13, 2010
    Posts:
    12
    Forgive my n00b-dom, but how would I add your script to my character? I'm assuming gameObject.AddComponent ("HorizontalMove"), but am I wrong/what next?
     
    Last edited: Sep 29, 2010
  21. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Why can't you add it in the Editor?
     
  22. agirardi24

    agirardi24

    Joined:
    Sep 13, 2010
    Posts:
    12
    I got it in but the character won't stop dashing after double tap, I'm changing dash period to no effect. I am also using the custom reset before I change values in the editor.
     
    Last edited: Oct 4, 2010
  23. agirardi24

    agirardi24

    Joined:
    Sep 13, 2010
    Posts:
    12
    I also simplified my original code I this /**/ while running the other script. Still slow but I'm quite sure this is better. What this does is when I double tap makes the dash forward for one move call then goes back to walking. And like my last code, it's doing what I want just really slow.

    Code (csharp):
    1.  
    2. private float doubleTapToRunTime;
    3. private float lastTapTime;
    4. private bool moving;
    5. private bool tapToRun;
    6.  
    7. if(moving  horizontalDirection == 0)
    8. {
    9.         moving = false;
    10.         if(Time.time > lastTapTime + doubleTapToRunTime)
    11.         {
    12.             tapToRun = false;
    13.         }
    14. }
    15. else if(!moving  horizontalDirection != 0)
    16. {      
    17.         if(tapToRun)
    18.         {
    19.             tapToRun = false;
    20.             horizontalDirection *= dashSpeed;
    21.         }
    22.         else
    23.         {
    24.             tapToRun = true;
    25.             lastTapTime = Time.time;
    26.             if (horizontalDirection > 0)
    27.         {
    28.             horizontalDirection *= fowardSpeed;
    29.         }
    30.         else
    31.         {
    32.             horizontalDirection *= backSpeed;
    33.         }
    34.         }
    35.         moving = true;
    36. }
    37.  
    38.  
     
  24. ticTek

    ticTek

    Joined:
    Jun 9, 2013
    Posts:
    2
    HI Jessy, I manage implement a double tap feature i wanted, using your code and examples!. it was a great help! thanks for sharing!!
     
    Last edited: Sep 25, 2013