Search Unity

2D dodge roll

Discussion in 'Physics' started by polydark, Aug 8, 2016.

  1. polydark

    polydark

    Joined:
    Jul 26, 2016
    Posts:
    11
    hey everyone, i want to try dodge-rolling a dude similar to the dodge mechanic in Enter the Gungeon.
    i'm a coding noob and have this currently on a sprite with a Rigidbody2D component :

    Code (CSharp):
    1. Rigidbody2D rb2d;
    2.     public float moveSpeed; //speed var
    3.     public float roll; //roll distance
    4.  
    5.     void Start ()
    6.     {
    7.         rb2d = GetComponent<Rigidbody2D> ();
    8.  
    9.     }
    10.    
    11.  
    12.     void FixedUpdate ()
    13.     {
    14.         MovePlayer ();
    15.     }
    16.  
    17.  
    18.     void MovePlayer ()
    19.     {
    20.          //get H and V vars
    21.         float hMove = Input.GetAxisRaw ("Horizontal");
    22.         float vMove = Input.GetAxisRaw ("Vertical");
    23.  
    24.         //move player
    25.         Vector2 movement = new Vector2 (hMove, vMove);
    26.         rb2d.velocity = movement * moveSpeed;
    27.  
    28.  
    29.          //check for space key to roll player only when moving
    30.         if (Input.GetKeyDown (KeyCode.Space) && movement.x != 0)
    31.         {
    32.             // dodge/roll player left/right
    33.         }
    34.         else if (Input.GetKeyDown (KeyCode.Space) && movement.y != 0)
    35.         {
    36.             // dodge/roll player up/down
    37.         }
    38.     }
    am i on the right path and if so how would i actually dodge-roll the player in the direction hes going?
     
  2. polydark

    polydark

    Joined:
    Jul 26, 2016
    Posts:
    11
    Ok so i played around and got this :

    Code (CSharp):
    1.         Rigidbody2D rb2d;
    2.     public float moveSpeed; //speed var
    3.     public float roll; //roll distance
    4.  
    5.     void Start ()
    6.     {
    7.         rb2d = GetComponent<Rigidbody2D> ();
    8.  
    9.     }
    10.    
    11.  
    12.     void FixedUpdate ()
    13.     {
    14.         MovePlayer ();
    15.     }
    16.  
    17.  
    18.     void MovePlayer ()
    19.     {
    20.          //get H and V vars
    21.         float hMove = Input.GetAxisRaw ("Horizontal");
    22.         float vMove = Input.GetAxisRaw ("Vertical");
    23.  
    24.         //move player
    25.         Vector2 movement = new Vector2 (hMove, vMove);
    26.         rb2d.velocity = movement * moveSpeed;
    27.  
    28.  
    29.          //check for space key to roll player
    30.         if (Input.GetKeyDown (KeyCode.Space) && movement.x != 0)
    31.         {
    32.             // dodge/roll player left/right
    33.             rb2d.velocity = new Vector2((hMove * moveSpeed) * roll, rb2d.velocity.y);
    34. // play roll sprite animation
    35.         }
    36.         else if (Input.GetKeyDown (KeyCode.Space) && movement.y != 0)
    37.         {
    38.             // dodge/roll player up/down
    39.             rb2d.velocity = new Vector2(rb2d.velocity.x, (vMove * moveSpeed) * roll);
    40.             // play roll sprite animation
    41.         }
    42.     }
    it sort of works but when you press space then the sprite is "instantly teleported" a few spaces over, don't know if the roll animation would make it look smoother when i add it, as the sprite is currently a single frame

    i read in the API about a Vector3.MoveTowards function, would something like that work better and smoother?
     
  3. bubba_nate

    bubba_nate

    Joined:
    Jan 2, 2016
    Posts:
    6
    I'm more of a theory guy than an actual code guy. I can do the code, but what I love is the theory behind it.

    Your movement system's going to be a bit wonky with speed, you'll go faster diagonally. Do movement.normalize * moveSpeed on the line where you set velocity and that will fix it. movement is your direction, you should always normalize it or else you'll end up with weirdness due to your direction vector having varying lengths.

    Anyways, why not just make the dodge roll lock movement to the last moved-in direction and set movespeed higher, plus your invincibility if necessary?

    Dodgecount is an int, it's the number of frames until the dodge is over. If it isn't zero, you're dodging, use this instead of a dedicated boolean.
    Dodgevect is a vector2, it takes the dodge direction and stores it independently of movement.
    dodgeSpeed is how fast to go during a dodge.

    try something like this
    Code (csharp):
    1. if (Input.getKeyDown(KeyCode.Space) && movement != Vector2.zero && dodgecount = 0) //vector2.zero should be  (0,0) which movement will be if you're not moving.
    2. {
    3. dodgecount = 60;//[frames for which to dodge here, man.]
    4. dodgevect=movement.normalize;
    5. }
    6. //What all this does is set a timer for the dodge and record what direction you're dodging in, if you're moving, trying to dodge, and not standing perfectly still.
    7.  
    8.  
    9. if (dodgecount != 0) {
    10. dodgecount -= 1; //Does this work in c#? reduce dodgecount by one somehow else if it doesn't.
    11. rb2d.velocty = dodgevect.normalize * dodgeSpeed; //Yes, it's already supposed to have a magnitude of one, but it's not a bad idea to be safe.
    12. }
    13. //If you're still dodging (counter isn't zero yet), move in the dodge direction at the dodge speed.
    As long as this is after your basic movement, you'll be fine, it'll do basic movement and then that will get ovewritten by the dodge.

    Note that if dodgecount ever goes BELOW zero, you'll be stuck in an infinite dodge. Add a failsafe to that if you wish, or use it to your advantage.

    This won't do what you're currently doing, which is teleporting. You're looking for a roll, which in EtG is just constant movement in one direction and an invincibility timer.

    EDIT: you look like you were on the right path and I don't see why you were teleporting, but good luck. Hope you don't hate me for doing everything for you. I had the normalization issue before and realized it, but tried to fix it with faulty, unreliable trig because I didn't know about vector3.normalize. It sucked and I don't want anyone else to have to do that when they don't have to.

    EDIT EDIT: SEMICOLONS GET ME EVERY TIME DANGIT WHY
     
    Last edited: Aug 11, 2016
    Ledesma099 likes this.
  4. polydark

    polydark

    Joined:
    Jul 26, 2016
    Posts:
    11
    Hey bubba_nate, thank you very much for the reply! this is exactly the kind of thing i was looking for. I am very new to any kind of programming and am very grateful to other people when they take the time to send a code snippet for me to analyze, experiment with and inevitably learn something new. The theory behind your code makes a lot of sense and i am going to try it out as soon as i get home.

    And also thanks for the letting me know about vector3.normalize. I actually have found in a previous project that the dude walks faster when going diagonally but of course didn't have the experience yet to know exactly why!

    When i get home with a new idea for some code, or a new angle to go with (like what you gave me here) i feel a bit like Dr Frankenstein going about a new experiment knowing full well that the monster might try and kill me afterwards xD

    Will let you know how i fare, thanks again man!
     
  5. jleven22

    jleven22

    Joined:
    Mar 26, 2019
    Posts:
    421
    Bringing this back to the surface as I'm attempting the same thing.

    I've made adjustments to suit my script, but I'm getting an error that I'm not familiar with:

    "Operator '!=' is ambiguous of operands of type Vector3 and Vector2"

    I'm fairly new to coding so I could use some hand-holding if possible.

    Code (CSharp):
    1.     private void Move()
    2.     {
    3.         transform.position = transform.position + movement * speed * Time.deltaTime;
    4.         rb.velocity = new Vector2(movement.x, movement.y);
    5.  
    6.         if (Input.GetButtonDown("Dodge") && movement != Vector2.zero && dodgeCount = 0) //vector2.zero should be  (0,0) which movement will be if you're not moving.
    7.         {
    8.             dodgeCount = 60;//[frames for which to dodge here, man.]
    9.             dodgeVect = movement.normalized;
    10.         }
    11.         //What all this does is set a timer for the dodge and record what direction you're dodging in, if you're moving, trying to dodge, and not standing perfectly still.
    12.  
    13.  
    14.         if (dodgeCount != 0)
    15.         {
    16.             dodgeCount -= 1; //Does this work in c#? reduce dodgecount by one somehow else if it doesn't.
    17.             rb.velocity = dodgeVect.normalized * dodgeSpeed; //Yes, it's already supposed to have a magnitude of one, but it's not a bad idea to be safe.
    18.         }
    19.         //If you're still dodging (counter isn't zero yet), move in the dodge direction at the dodge speed.
    20.     }
     
  6. jleven22

    jleven22

    Joined:
    Mar 26, 2019
    Posts:
    421
    Updated all to Vector3, so got that figured out!

    Now my issue is that the dodge is just freezing the player in space, while the running animation continues.

    Code (CSharp):
    1.     private void Move()
    2.     {
    3.         transform.position = transform.position + movement * speed * Time.deltaTime;
    4.         rb.velocity = new Vector3(movement.x, movement.y);
    5.  
    6.         if (Input.GetKeyDown(KeyCode.Space) && movement != Vector3.zero && dodgeCount == 0) //vector2.zero should be  (0,0) which movement will be if you're not moving.
    7.         {
    8.             dodgeCount = 60;//[frames for which to dodge here, man.]
    9.             dodgeVect = movement.normalized;
    10.         }
    11.         //What all this does is set a timer for the dodge and record what direction you're dodging in, if you're moving, trying to dodge, and not standing perfectly still.
    12.  
    13.  
    14.         if (dodgeCount != 0)
    15.         {
    16.             dodgeCount -= 1; //Does this work in c#? reduce dodgecount by one somehow else if it doesn't.
    17.             rb.velocity = dodgeVect.normalized * dodgeSpeed; //Yes, it's already supposed to have a magnitude of one, but it's not a bad idea to be safe.
    18.         }
    19.         //If you're still dodging (counter isn't zero yet), move in the dodge direction at the dodge speed.
    20.     }