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

Question bools and if-statement logic

Discussion in 'Scripting' started by antipinno, Apr 10, 2021.

  1. antipinno

    antipinno

    Joined:
    Apr 4, 2021
    Posts:
    8
    Hi Guys, I was making a top down movement system. problem is that when I hold 'A' key to move left simultaneously press 'D' key the player change its direction and start moving in right and same happens with W and S keys. I cannot use simple if statements to change direction(using if statements instead of else-if makes the player go diagonal).I think what i need is when one if-statement is running then other should stop working. I tried to use bools to manage the if statements but it didn't work. Here is the code:
    Code (CSharp):
    1.  
    2. void Move()
    3.     {
    4.         float movX = 0;
    5.         float movY = 0;
    6.  
    7.         if (Input.GetKey(KeyCode.D) )
    8.         {
    9.             movX = 1f;
    10.         }
    11.         else if (Input.GetKey(KeyCode.A))
    12.         {
    13.             movX = -1f;
    14.         }
    15.        
    16.         else if (Input.GetKey(KeyCode.W))
    17.         {
    18.             movY = 1f;
    19.         }
    20.         else if (Input.GetKey(KeyCode.S))
    21.         {
    22.             movY = -1f;
    23.         }
    24.  
    25.         Vector2 movDir = new Vector2(movX, movY);
    26.  
    27.         idle = movX == 0 && movY == 0;
    28.         if (idle)
    29.         {
    30.             rigidbody2d.velocity = Vector2.zero;
    31.         }
    32.         else
    33.         {
    34.             rigidbody2d.velocity = movDir * speed;
    35.         }
    36.     }
    I have been staring at this code for long enough. Can anyone give me some guidance.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    You do not want the
    else
    statement on line 16.
     
    antipinno likes this.
  3. antipinno

    antipinno

    Joined:
    Apr 4, 2021
    Posts:
    8
    Thanks Kurt for replying, I don't want diagonal movement in the game so making it
    if
    will do the opposite. Problem is with 'A' and 'D' . If I press 'D' key while holding 'A' it changes direction to right. Is there any way to make first
    if
    statement(Line 7) stop when second
    else
    statement (Line 11) is running? I mean I know we can use
    Bool
    to tackle this problem but the logic is not clicking in my mind.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    Do you mean that want only one axis of motion to be possible at once? eg only left, right, up or down (or sit still)?

    It seems to me your original code would do that. If it does not, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run?
    - what are the values of the variables involved? Are they initialized?

    Knowing this information will help you reason about the behavior you are seeing.
     
    antipinno likes this.
  5. antipinno

    antipinno

    Joined:
    Apr 4, 2021
    Posts:
    8
    Oh Yes code is working fine (kind of) and yes I want motion in one axis at a time I don't want any diagonal movements . Problem is when I am holding 'A' key it moves the player left but simultaneously if I hold 'D' key it moves the player in right direction(and I am still holding the 'A' key). I think what I am looking for is when one if statement is running others should stop working. (I did use Debug.Log statements to track the movDir Vector and it was working fine. Problem is with the if statements.)
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,520
    That is a little bit trickier and requires maintaining from frame to frame which key was down.

    What you would need to do is track which key was active last frame, check if it is still active this frame, and if so, disregard ALL other keys. Only when the key from the previous frame is not down would you consider checking the other keys.
     
    antipinno likes this.
  7. Flawkee

    Flawkee

    Joined:
    Sep 24, 2020
    Posts:
    2
    Why using GetKey instead of GetButton? Using GetButton / GetAxis allow the player to map the key as he likes.
    In addition, it is not recommended editing the velocity directly.
    One last thing that I cannot see here but you could have implemented it somewhere else, always multiply your desired move speed by Time.deltaTime - If you will not, to player movement speed will be inconsistent during gameplay and across different platforms.

    Now basically the problem is that you have 4 different if statements that the code checks 1 by 1.
    That means that if you hold the D key, and after a while you hold the A key as well, the player will continue to go right since the if statement of D key is first.
    The same goes if you hold A and then you hold W well. But if you will then hold D as well, the player will go right.

    Just a note, I barely know any games that don't allow interruption and forcing you to move by one direction if you hit a key no matter what key your press later on.
    But the piece of code below is a solution for your problem I came up real quick. I can't tell you if it's the most efficient way, it probably isn't, but it should give you a clue.
    It feels clunky in my opinion though.

    Code (CSharp):
    1. public class YourClass : MonoBehaviour
    2. {
    3.  
    4.     bool isDPressed = false;
    5.     bool isAPressed = false;
    6.     bool isWPressed = false;
    7.     bool isSPressed = false;
    8.     bool isAnyKeyPressed = false;
    9.     void Update()
    10.     {
    11.         GetPlayerMovement();
    12.     }
    13.  
    14.     private void GetPlayerMovement()
    15.     {
    16.         float movX = 0;
    17.         float movY = 0;
    18.  
    19.         if (Input.GetKey(KeyCode.D) && !isAnyKeyPressed || Input.GetKey(KeyCode.D) && isAnyKeyPressed && isDPressed)
    20.         {
    21.             movX = 1f;
    22.             isAnyKeyPressed = true;
    23.             isDPressed = true;
    24.         }
    25.         else if (Input.GetKey(KeyCode.A) && !isAnyKeyPressed || Input.GetKey(KeyCode.A) && isAnyKeyPressed && isAPressed)
    26.         {
    27.             movX = -1f;
    28.             isAnyKeyPressed = true;
    29.             isAPressed = true;
    30.         }
    31.  
    32.         else if (Input.GetKey(KeyCode.W) && !isAnyKeyPressed || Input.GetKey(KeyCode.W) && isAnyKeyPressed && isWPressed)
    33.         {
    34.             movY = 1f;
    35.             isAnyKeyPressed = true;
    36.             isWPressed = true;
    37.         }
    38.         else if (Input.GetKey(KeyCode.S) && !isAnyKeyPressed || Input.GetKey(KeyCode.S) && isAnyKeyPressed && isSPressed)
    39.         {
    40.             movY = -1f;
    41.             isAnyKeyPressed = true;
    42.             isSPressed = true;
    43.         }
    44.         else
    45.         {
    46.             isDPressed = false;
    47.             isAPressed = false;
    48.             isWPressed = false;
    49.             isSPressed = false;
    50.             isAnyKeyPressed = false;
    51.         }
    52.  
    53.         Vector2 movDir = new Vector2(movX, movY);
    54.         transform.Translate(movDir * speed * Time.deltaTime);
    55.     }
    56. }
    57.  
     
    antipinno likes this.
  8. antipinno

    antipinno

    Joined:
    Apr 4, 2021
    Posts:
    8
    Sorry for late reply. This worked like charm. I knew we can manage this with booleans but logic was not clicking in my head. I'll keep those tips in mind. Thanks