Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Bug Putting an Up/Down movement through a timer

Discussion in 'Scripting' started by gravesaad, Jul 31, 2023.

  1. gravesaad

    gravesaad

    Joined:
    Jul 7, 2023
    Posts:
    9
    Hi everybody,

    I've been trying to code a 2D Up/Down movement that uses no gravity, and is meant to lead to a single vertical movement by YAxis, so i need a timer, otherwise pressing a key just makes the gameObject moves continuously as long as the key is pressed and this is not what i want, i want a rigid, one time, regular movement.

    But when i put it through the timer, the jump only works from time to time independently of the condition put in the timer.

    Here is the code

    Code (CSharp):
    1. public class Player : MonoBehaviour
    2. {
    3.  
    4.     public float playerSpeed;
    5.  
    6.     private Rigidbody2D rb;
    7.      
    8.     private bool isJumping;
    9.  
    10.     float vertical;
    11.     float timer;
    12.      float waitTime = 10f;
    13.     float count = 0;
    14.  
    15. void Start()
    16.     {
    17.  
    18.         rb = GetComponent<Rigidbody2D>();
    19.         jumpNumber = 0;
    20.         isJumping = false;
    21.      
    22.        
    23.  
    24.     }
    25.  
    26. void Update()
    27.     {
    28.  
    29.        
    30.  
    31.  
    32.         if (isJumping)
    33.         {
    34.  
    35.             timer += Time.fixedDeltaTime;
    36.          
    37.  
    38.  
    39.            
    40.  
    41.             if (timer >= waitTime)
    42.             {
    43.  
    44.                 count++;
    45.                 timer -= waitTime + Time.fixedDeltaTime;
    46.                 Debug.Log("lapsed" + waitTime);
    47.                 Debug.Log("And count is" + count);
    48.                 timer = 0f;
    49.                 isJumping = false;
    50.                 waitTime = 10f;
    51.              
    52.                 Debug.Log("Is jumping is" + isJumping.ToString());          
    53.  
    54.  
    55.             }
    56.  
    57.  
    58.  
    59.         }
    60.  
    61.      
    62.  
    63.         if (Input.GetKey(KeyCode.UpArrow) && !isJumping)
    64.         {
    65.             Debug.Log("Should jump here up");
    66.             vertical = 18f;
    67.             isJumping = true;
    68.             Debug.Log("Vertical is" + vertical);
    69.         }
    70.  
    71.         else if (Input.GetKey(KeyCode.DownArrow) && !isJumping)
    72.         {
    73.             Debug.Log("Should jump here down");
    74.  
    75.             vertical = -18f;
    76.             isJumping = true;
    77.             Debug.Log("Vertical is" + vertical);
    78.         }
    79.  
    80.         else
    81.         {
    82.             vertical = 0;
    83.  
    84.         }
    85.  
    86.  
    87. void FixedUpdate()
    88.     {    
    89.        
    90.         rb.velocity = new Vector2(0, vertical * (playerSpeed * 3 ));
    91.        
    92.     }
    I know the problem isn't exactly with the timer, because when i press the key, i get the Debug text in the log ("Should jump here").

    But the FixedUpdate doesn't get called when there is a change in the vertical variable, or it gets called only sporadically, one press there is a movement, two press there is none, then two consecutive press will work etc etc.

    Any idea on how to remedy this ?

    Thank you in advance.
     
  2. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    For starters, I would have your variables "isJumping" and "timer" both as public so you can watch them in the Inspector. So you can verify the time, and when the bool of jump is finally false.

    Secondly, I'd change your GetKey calls to GetKeyDown:
    Code (CSharp):
    1. if (Input.GetKeyDown(KeyCode.UpArrow) && !isJumping)
    2.         {
    3.             Debug.Log("Should jump here up");
    4.             vertical = 18f;
    5.             isJumping = true;
    6.             Debug.Log($"Vertical is {vertical}"); // interpolate
    7.         }
    If you're only requiring them to happen one time. GetKey() would be used more for like move left or right(like super mario), constantly moving at speed each frame.

    I'm a little confused on the whole method, so those are best things I can throw out at the moment. Hopefully something helps!
     
    gravesaad likes this.
  3. gravesaad

    gravesaad

    Joined:
    Jul 7, 2023
    Posts:
    9
    Hey, thanks for the reply.

    The problem isn't in the Input.GetKeyDown condition, because i get the Debug text everytime it is pressed, at the right moment.

    The problem is most certainly with the update function and how/when "Rb.velocity = " access to and updates the value of the vertical variable.

    I'm sorry for causing the confusion, i'm confused myself, i'm just trying to code a simple "one press" movement that moves the player one axis up or one axis down, all the methods and tutorials i've followed either :

    - Use continuous movement, which is easy to code with updates, as long as you are pressing the player continues moving.
    - Or rely on gravity.
    - Or rely on collusion + gravity with the ground as the trigger for when the jump starts.

    While in my specific case there is none of those.

    I've tried to just replaced the method wholesale with :
    Code (CSharp):
    1. if (Input.GetKey(KeyCode.UpArrow) && !isJumping && playerPosition.y < 1.38f)
    2.         {
    3.             Debug.Log("Should jump up");
    4.             vertical = 1.5f;
    5.             transform.position = new Vector3(positionX, positionY + vertical, 0);
    6.             isJumping = true;
    7.             jumpSoundEffect.Play();
    8.        
    9.             Debug.Log("they player position = " + playerPosition.y);
    10.  
    11.         }
    (and removed the rb.velocity in the update )

    It works and the jump is regular, but it isn't smooth at all so i'm still searching for a more elegant method.
     
  4. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Well:
    Code (CSharp):
    1. transform.position = new Vector3(positionX, positionY + vertical, 0);
    2. // would be better stated as
    3. transform.Translate(0, vertical, 0);
    But as far as not being smooth, that all depends on the speed it's moving and what the frame count is via Application.targetFramerate;.

    As if you're moving one unit each frame, it's going to "teleport" each unit each frame. And if the frameRate is set to say 60, you could have the movement calculate within FixedUpdate(), as fixedUpdate would run more times in it's frames(technically speaking), you'd just have to modify the speed value.

    But in your original question, it seemed as though "Jump" was staying true, so just wanted you to verify that it was indeed turning false.
     
    gravesaad likes this.
  5. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I must apologize, just looking at the code didn't fully make me think like the compiler! I tested and played with your original code, and ignored the whole Rigidbody setup. But since it's working now, change it however you like.

    Code (CSharp):
    1. public class Test : MonoBehaviour
    2. {
    3.     public float playerSpeed;
    4.     private Rigidbody2D rb;
    5.     public bool isJumping;
    6.  
    7.     public float vertical;
    8.     public float timer;
    9.     float speed = 0.18f;
    10.     float waitTime = 10f;
    11.     float count = 0;
    12.  
    13.     void Start()
    14.     {
    15.         rb = GetComponent<Rigidbody2D>();
    16.     }
    17.  
    18.     void Update()
    19.     {
    20.         if (!isJumping)
    21.         {
    22.             if (vertical != 0) { vertical = 0; }
    23.             if (Input.GetKey(KeyCode.UpArrow))
    24.             {
    25.                 vertical = speed;
    26.                 isJumping = true;
    27.             }
    28.             if (Input.GetKey(KeyCode.DownArrow))
    29.             {
    30.                 vertical = -speed;
    31.                 isJumping = true;
    32.             }
    33.         }
    34.         else
    35.         {
    36.             if (timer >= waitTime)
    37.             {
    38.                 count++;
    39.                 timer -= waitTime + Time.fixedDeltaTime;
    40.                 print($"lapsed {waitTime}");
    41.                 print($"And count is {count}");
    42.                 timer = 0f;
    43.                 isJumping = false;
    44.             }
    45.         }
    46.     }
    47.  
    48.     void FixedUpdate()
    49.     {
    50.         if (isJumping) { timer += Time.fixedDeltaTime; }
    51.         //rb.velocity = new Vector2(0, vertical * (playerSpeed * 3));
    52.         transform.Translate(0, vertical, 0);
    53.     }
    54. }
     
    Last edited: Aug 3, 2023
  6. gravesaad

    gravesaad

    Joined:
    Jul 7, 2023
    Posts:
    9
    Hello,

    Thanks a lot for trying to help, unfortunately it doesn't work, the player moves all the way to top of the screen or all the way to bottom of the screen when i implement this solution, even when i tinker with waittime, moving it from 10f to 9, 7, 8f, to 0.7f (which was the original wait time that was adapted to my jump).

    If i change this

    Code (CSharp):
    1. if (timer >= waitTime)
    2.             {
    3.                 count++;
    4.                 timer -= waitTime + Time.fixedDeltaTime;
    5.                 print($"lapsed {waitTime}");
    6.                 print($"And count is {count}");
    7.                 timer = 0f;
    8.                 isJumping = false;
    9.             }
    10.         }
    to this

    Code (CSharp):
    1. if (timer >= waitTime / 20)
    2.             {
    3.                 count++;
    4.                 timer -= waitTime + Time.fixedDeltaTime;
    5.                 print($"lapsed {waitTime}");
    6.                 print($"And count is {count}");
    7.                 timer = 0f;
    8.                 isJumping = false;
    9.             }
    10.         }
    The problem of the player moving all the way up is solved, but at the expense of the movement being continuous, as long as the touch is pressed the player keeps moving up, instead of the one up jump i was looking for.

    Now, this is the last solution i implemented :

    Code (CSharp):
    1.  
    2.  
    3. void Update()
    4.  
    5. {
    6.  
    7. if (isJumping)
    8.         {
    9.             timer += Time.fixedDeltaTime;
    10.  
    11.  
    12.             if (timer >= waitTime / 20)
    13.             {
    14.                 vertical = 0;
    15.             }
    16.  
    17.  
    18.             if (timer >= waitTime)
    19.             {
    20.  
    21.                 count++;
    22.                 timer -= waitTime + Time.fixedDeltaTime;
    23.                 Debug.Log("lapsed" + waitTime);
    24.                 Debug.Log("And count is" + count);
    25.  
    26.                 timer = 0f;
    27.                 isJumping = false;
    28.                 waitTime = 0.7f;
    29.  
    30.                 Debug.Log("Is jumping is" + isJumping.ToString());
    31.  
    32.            }
    33.  
    34.         }
    35.  
    36.          
    37.  
    38.         if (Input.GetKey(KeyCode.UpArrow) && !isJumping)
    39.         {
    40.             Debug.Log("Should jump up");
    41.             vertical = 1.5f;
    42.             transform.position = new Vector3(positionX, positionY + vertical, 0);
    43.             isJumping = true;  
    44.  
    45.         }
    46.  
    47.         else if (Input.GetKey(KeyCode.DownArrow) && !isJumping )
    48.         {
    49.             Debug.Log("Should jump down");
    50.             vertical = 1.5f;
    51.             transform.position = new Vector3(positionX, positionY - vertical, 0);
    52.             isJumping = true;
    53.  
    54.         }
    55. }
    56.  
    57.  
    58.  
    59.  
    It works at least in fulfilling all conditions : One discontinuous move by a specific axis, instead of slowly moving up while the key is pressed. The jump isn't as smooth as i want it but maybe i can't have my cake and eat it too.

    Thank you again for your time.
     
  7. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    The only 2 variables that would need changed are:
    Code (CSharp):
    1. float speed = 0.18f;
    2. float waitTime = 10f;
    If your object keeps moving longer than you want, lower the
    waitTime
    . As while playing with it, I never understood why that time was so long, but I assumed that's what you wanted.

    If your object isn't moving fast enough, increase the
    speed
    . As this will change how much movement happens within each frame(or in your case each fixedUpdate() frame).

    Other than that, nothing would need changed. Unless if something somehow was different for
    rb.velocity
    . But from what I understood with your implementation, that was what you wanted.

    Your original issue was:
    Code (CSharp):
    1. if (Input.GetKey(KeyCode.UpArrow) && !isJumping)
    2.         {
    3.             Debug.Log("Should jump here up");
    4.             vertical = 18f;
    5.             isJumping = true;
    6.             Debug.Log("Vertical is" + vertical);
    7.         }
    8.         else if (Input.GetKey(KeyCode.DownArrow) && !isJumping)
    9.         {
    10.             Debug.Log("Should jump here down");
    11.             vertical = -18f;
    12.             isJumping = true;
    13.             Debug.Log("Vertical is" + vertical);
    14.         }
    15.         else
    16.         {
    17.             vertical = 0;
    18.         }
    As this looks like "isJumping" should stay on, and "vertical = 0" wouldn't happen until "isjumping" equals false. Which is false, as the question asks "if key.down true AND !isJumping" which would instantly be false after pressing up/down key. Then read down, to eventually making vertical 0 in the next frame.

    So by giving a proper if isJumping or not, vertical will now stay the speed you want it to, while jump is true. Just play with the 2 variables I mentioned at first, to get your desired effect. Cheers!
     
    Last edited: Aug 3, 2023
    gravesaad likes this.
  8. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Which to double check, the complete functionality of what you want, looks similar to what this video shows?
    Of course assuming waitTime and speed not exactly right

     
  9. gravesaad

    gravesaad

    Joined:
    Jul 7, 2023
    Posts:
    9
    Exactly like this.

    Thank you a lot, your solution after some tweaking spared me a headache that would have lasted days, here is the final solution i got to

    Code (CSharp):
    1. void Update()
    2.     {
    3.        
    4.  
    5.         bottom = new Rect(0, 0, Screen.width, Screen.height / 4);
    6.         top = new Rect(0, Screen.height / 4, Screen.width, Screen.height / 1.35f);
    7.  
    8.  
    9.  
    10.  
    11.         if (timer >= waitTime / 5)
    12.         {
    13.             vertical = 0f;
    14.  
    15.         }
    16.  
    17.  
    18.         if (!isJumping)
    19.             {
    20.                 if (vertical != 0) { vertical = 0; }
    21.                 if (Input.GetKey(KeyCode.UpArrow))
    22.                 {
    23.                     vertical = speed;
    24.                     isJumping = true;
    25.                 }
    26.                 if (Input.GetKey(KeyCode.DownArrow))
    27.                 {
    28.                     vertical = -speed;
    29.                     isJumping = true;
    30.                 }
    31.             }
    32.             else
    33.             {
    34.                 if (timer >= waitTime)
    35.                 {
    36.                     count++;
    37.                     timer -= waitTime + Time.fixedDeltaTime;
    38.                     print($"lapsed {waitTime}");
    39.                     print($"And count is {count}");
    40.                     timer = 0f;
    41.                     isJumping = false;
    42.                    
    43.                 }
    44.             }      
    45.  
    46.      
    47.  
    48. void FixedUpdate()
    49.     {
    50.  
    51.         if (isJumping) { timer += Time.fixedDeltaTime; }
    52.         //rb.velocity = new Vector2(0, vertical * (playerSpeed * 3));
    53.         transform.Translate(0, vertical, 0);
    54.  
    55.     }
    56.  
    57.  
    And finally it works.

    Muchas Gracias.