Search Unity

2D MMBN style movement help?

Discussion in '2D' started by Elusive139, Feb 16, 2020.

  1. Elusive139

    Elusive139

    Joined:
    Apr 7, 2019
    Posts:
    6
    So I wanted to try and make a Battle network style movement system, where you can move from panel to panel like your teleporting, and I've got something that kind of works using raycasts, but it moves a bit too quickly. i can move almost diagonally if I press two movement keys at once, which isn't really something I want. any suggestions?
    Code (CSharp):
    1. public class PlayerMovement : MonoBehaviour
    2. {
    3.     public Transform player;
    4.     public int distance = 30;
    5.     public Transform Middle;
    6.  
    7.     bool left;
    8.     bool right;
    9.     bool up;
    10.     bool down;
    11.  
    12.  
    13.     void Start()
    14.     {
    15.         Vector3 start = new Vector3(Middle.position.x, Middle.position.y+1, Middle.position.z);
    16.         player.position = start;
    17.         Physics2D.queriesStartInColliders = false;
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         /*
    24.         left = Input.GetKeyDown(KeyCode.A);
    25.         right = Input.GetKeyDown(KeyCode.D);
    26.         up = Input.GetKeyDown(KeyCode.W);
    27.         down = Input.GetKeyDown(KeyCode.S);*/
    28.  
    29.             moveLeft();
    30.             moveRight();
    31.             moveUp();
    32.             moveDown();
    33.  
    34.     }
    35.     public void moveLeft()
    36.     {
    37.         left = Input.GetKeyDown(KeyCode.A);
    38.         if (left)
    39.         {
    40.             RaycastHit2D hitLeft = Physics2D.Raycast(player.position, -player.transform.right, distance);
    41.             Vector3 move = new Vector3(hitLeft.transform.position.x, hitLeft.transform.position.y, hitLeft.transform.position.z);
    42.             player.position = move;
    43.         }
    44.     }
    45.     public void moveRight()
    46.     {
    47.  
    48.         right = Input.GetKeyDown(KeyCode.D);
    49.         if (right)
    50.         {
    51.             RaycastHit2D hitRight = Physics2D.Raycast(player.position, player.transform.right, distance);
    52.             Vector3 move = new Vector3(hitRight.transform.position.x, hitRight.transform.position.y, hitRight.transform.position.z);
    53.             player.position = move;
    54.         }
    55.     }
    56.     public void moveUp()
    57.     {
    58.         up = Input.GetKeyDown(KeyCode.W);
    59.         if (up)
    60.         {
    61.             RaycastHit2D hitUp = Physics2D.Raycast(player.position, player.transform.up, distance);
    62.             Vector3 move = new Vector3(hitUp.transform.position.x, hitUp.transform.position.y, hitUp.transform.position.z);
    63.             player.position = move;
    64.         }
    65.     }
    66.     public void moveDown()
    67.     {
    68.         down = Input.GetKeyDown(KeyCode.S);
    69.         if (down)
    70.         {
    71.             RaycastHit2D hitDown = Physics2D.Raycast(player.position, -player.transform.up, distance);
    72.             Vector3 move = new Vector3(hitDown.transform.position.x, hitDown.transform.position.y, hitDown.transform.position.z);
    73.             player.position = move;
    74.         }
    75.     }
    76. }
    77.  
    I really just need a way to slow it down where it doesn't feel like input lag, but you cant get to the other corner of the area in less than a second.
     
    Last edited: Feb 16, 2020
  2. Primoz56

    Primoz56

    Joined:
    May 9, 2018
    Posts:
    369
    Use LERP when assigning player position
     
  3. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,807
    The way you have it currently, you can press multiple directions in one frame, and move multiple directions in one frame.

    The most straightforward solution is to create an artificial delay to prevent multiple inputs per interval. As a personal rule of thumb, anything less than 100ms will feel acceptable and "instantaneous". At 60fps, each frame is 16ms, so in theory you can have up to 6 frames of lag to process an input (you can decide for yourself what feels acceptable).

    However, that artificial delay can be longer if it comes from the player having a "movement" time (a movement animation as @Primoz56 suggested), or in the case of MMBN, a "cooldown" after teleporting to the target location where inputs are not accepted. In any case, it's very important that there be a visual indicator, for example in MMBN there is a "teleport" animation to help the player time sequential movement inputs.

    You may opt to queue the next input if it's received within some amount of time of the cooldown finishing, that way players won't feel as though inputs are dropped if they press the key a frame early.

    A good way to decide how to constrain inputs is to create a few worst-case scenarios and define what the result should be, then create code that enforces that. You can also play MMBN and try those scenarios out and see how the game handles it. For example:
    • A player mashes many inputs in a single frame
      • possible solutions - first input works, last input works, all inputs queue
     
    Last edited: Feb 17, 2020