Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Inconsistent movement problem - code snippet and link to game included

Discussion in '2D' started by druphoria, Aug 11, 2014.

  1. druphoria

    druphoria

    Joined:
    Jul 26, 2014
    Posts:
    4
    Hi all. I'm new to Unity2D and worked on a game with a few other mostly beginners. I was in charge of all code related to player movement, and the algorithm that I ended up using involved modifying the player velocity (in FixedUpdate) in response to left/right input in order to allow for acceleration. It also involves letting the player come to a gradual stop, rather than stopping abruptly, by decelerating gradually when he lets go of the left/right button. I've attached the bare bones algorithm below, but basically the way it works is this:
    - If the player presses the left/right directional button and he's not going the max speed yet, increase his speed by a fixed amount (a variable named acceleration).
    - If the player is not pressing left or right but he is currently moving in either direction, then apply the deceleration value each FixedUpdate until he gets to zero.

    The problem is that the player does not seem to move a consistent distance when I press the left and right buttons. For example I might tap the left button once and the player goes a short distance, and then I tap it again and he goes a much longer distance, etc. I'm not sure why there is this variation but I find that it is a bit disruptive.

    Anyways, here is the game itself so that you can see what I'm talking about (it is still in the very early stages, so all you can do right now is move around):
    http://gamejolt.com/games/action/freefall/31146/

    Here's the code that controls the ground movement. Please let me know if you can help me figure out what is going on with the inconsistent movement. This is being called from FixedUpdate.

    Code (CSharp):
    1. public void Move() {
    2.         Vector2 movement = rigidbody2D.velocity;
    3.  
    4.         if(Input.GetAxis("Horizontal") < 0 && rigidbody2D.velocity.x > -maxSpeed) {
    5.             movement.x -= acceleration;
    6.             if(movement.x < -maxSpeed) {
    7.                 movement.x = -maxSpeed;
    8.             }
    9.         }
    10.         if(Input.GetAxis("Horizontal") > 0 && rigidbody2D.velocity.x < maxSpeed) {
    11.             movement.x += acceleration;
    12.             if(movement.x > maxSpeed) {
    13.                 movement.x = maxSpeed;
    14.             }
    15.         }
    16.  
    17.         if(Input.GetAxis("Horizontal") == 0) {
    18.             if(movement.x < 0) {
    19.                 movement.x += deceleration;
    20.                 if(movement.x > 0) {
    21.                     movement.x = 0;
    22.                 }
    23.             }
    24.             if(movement.x > 0) {
    25.                 movement.x -= deceleration;
    26.                 if(movement.x < 0) {
    27.                     movement.x = 0;
    28.                 }
    29.             }
    30.         }
    31.  
    32.         rigidbody2D.velocity = movement;
    33.     }
     
    Last edited: Aug 12, 2014
  2. Punchbag

    Punchbag

    Joined:
    Oct 30, 2012
    Posts:
    48
    I can't access your game right now because I'm at work, but you might find that you're better off putting this code into Update() and factoring time into the equation.

    Here's a hypothetical of what's happening.

    Assumed Constant: When you tap, you always hold the button for exactly 0.022s

    Scenario 1 (Short Distance): The game does a physics update at 0s, you then start holding the button as part of your tap at 0.17s. Physics update occurs at 0.02s. You then release at 0.039s. Physics update occurs at 0.04s. You had one FixedUpdate() of velocity building.

    Scenario 2 (Long Distance): The game does a physics update at 0s, you then start holding the button as part of your tap at 0.19s. Physics update occurs at 0.02s. Physics update occurs at 0.04s. You then release at 0.041. You had two FixedUpdates() of velocity building.

    Summary
    If you handle your input in Update(), then you'll get a much more granular effect. i.e. Velocity will be more representative of how long the button was held between physics updates occurring. As it currently stands, you're polling input every 0.02s, instead of 'as often as possible'.