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

Adding Dodge Roll button. Activates during attack.

Discussion in '2D' started by SuperHyperHedgey, May 5, 2022.

  1. SuperHyperHedgey

    SuperHyperHedgey

    Joined:
    Aug 20, 2017
    Posts:
    2
    Hello,

    I'm currently making a top-down 2d game and am trying to implement a dodge roll that launches the player in the direction they're moving and press the "Roll" button. I want to make it so that dodge roll is a complete movement transition, and doesn't teleport to a position in the distance desired.

    I've tried making this possible by using the AddForce method as well as testing the Rigidbody2d.Velocity (as shown below). Whenever I've attempted either method a roll in the desired direction isn't executed. However, when I press the "Attack" button it moves the player in the direction the roll was supposed to execute.

    Any explanation as to why the Roll velocity/Force takes effect only during the Attack Input, in the direction pressed.
    I would also appreciate being pointed in the right direction of how to code a better dodge roll.

    Below is the code I wrote up for player movement, attack, and roll:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class PlayerMove : BattleStats
    6. {
    7.     [SerializeField] float moveSpeed;
    8.     [SerializeField] float rollSpeed;
    9.     Vector2 movement;
    10.  
    11.     [SerializeField] float attackTime;
    12.  
    13.     public Rigidbody2D rb;
    14.     public bool canMove;
    15.  
    16.     public BoxCollider2D collide;
    17.  
    18.     public Animator anime;
    19.  
    20.     public AudioSource audioSource;
    21.     public AudioClip[] sword;
    22.     private AudioClip swordClip;
    23.  
    24.     // Start is called before the first frame update
    25.     void Start()
    26.     {
    27.         anime.SetFloat("Horizontal", 0);
    28.         anime.SetFloat("Vertical", -1);
    29.         audioSource = gameObject.GetComponent<AudioSource>();
    30.         canMove = true;
    31.         rb = GetComponent<Rigidbody2D>();
    32.     }
    33.  
    34.     // Update is called once per frame
    35.     void Update()
    36.     {
    37.         movement = Vector2.zero;
    38.         if (canMove)
    39.         {
    40.             movement.x = Input.GetAxisRaw("Horizontal");
    41.             movement.y = Input.GetAxisRaw("Vertical");
    42.         }
    43.         else if (Input.GetButtonDown("Attack"))
    44.         {
    45.             Debug.Log("Attack");
    46.             StartCoroutine(AttackCo());
    47.  
    48.             int index = Random.Range(0, sword.Length);
    49.             swordClip = sword[index];
    50.             audioSource.clip = swordClip;
    51.             audioSource.Play();
    52.         }
    53.         else if (Input.GetButtonDown("Roll"))
    54.         {
    55.             if (movement == Vector2.up)
    56.             {
    57.                 Debug.Log("Dodge up");
    58.                 rb.velocity = new Vector2(0, 1) * rollSpeed;
    59.  
    60.             }
    61.             if (movement == Vector2.down)
    62.             {
    63.                 Debug.Log("Dodge down");
    64.                 //rb.velocity = new Vector2(0, -1) * rollSpeed;
    65.             }
    66.             if (movement == Vector2.left)
    67.             {
    68.                 Debug.Log("Dodge left");
    69.                 //rb.velocity = new Vector2(-1, 0) * rollSpeed;
    70.             }
    71.             if (movement == Vector2.right)
    72.             {
    73.                 Debug.Log("Dodge right");
    74.                 //rb.velocity = new Vector2(1, 0) * rollSpeed;
    75.             }
    76.             /*else
    77.             {
    78.                 rb.velocity = new Vector2(0,0);
    79.             }*/
    80.         }
    81.         else
    82.         {
    83.             UpdateAnimationAndMove();
    84.  
    85.         }
    86.     }
    87.     void FixedUpdate()
    88.     {
    89.         if (canMove) // the canmove state makes it so that it's possible for the player to move or not during other actions
    90.         {
    91.             rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
    92.         }
    93.     }
    94.  
    95.     void UpdateAnimationAndMove()
    96.     {
    97.         if (movement != Vector2.zero && canMove)
    98.         {
    99.             FixedUpdate();
    100.             anime.SetFloat("Horizontal", movement.x);
    101.             anime.SetFloat("Vertical", movement.y);
    102.             anime.SetFloat("Speed", movement.sqrMagnitude);
    103.             anime.SetBool("moving", true);
    104.  
    105.         }
    106.         else
    107.         {
    108.             anime.SetBool("moving", false);
    109.         }
    110.     }
    111.     private IEnumerator AttackCo()
    112.     {
    113.         anime.SetBool("Attack", true);
    114.         canMove = false; // makes it so the move player can't move during an attack
    115.         //currently player can button mash to overpower the canMove = false state
    116.         yield return new WaitForSeconds(attackTime); //duration of when attack is effective              
    117.         anime.SetBool("Attack", false);
    118.         canMove = true; //returns the player into a state so they can move again
    119.         yield return null;
    120.     }
    121. }
     
  2. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    What do you want to use to cause it to move? You're setting velocity but then you're also telling it to move explicitly to a position. If I asked you to move North (the velocity) but also move to this specific position South (MovePosition) you wouldn't be able to do both.

    Is this a Kinematic body because MovePosition/MoveRotation are typically used for Kinematic motion not Dynamic motion (Dynamic body). I ask this because you said you tried adding force but that wouldn't work on a Kinematic body.
    • AddForce will modify velocity during the simulation step.
    • Setting Velocity will result in it being integrated to a position change during the simulations step.
    • MovePosition will move to that position during the simulation step and ignore any existing velocity, gravity, drag etc.
    All these movement methods work but ultimately they do the same thing (cause a position change). You just need to sort out your script logic of what you use and when.
     
  3. SuperHyperHedgey

    SuperHyperHedgey

    Joined:
    Aug 20, 2017
    Posts:
    2
    Ah ok. I wasn't clear on my knowledge that MovePosition and AddForce/velocity would interfere with one another. The object is set to a Dynamic body, not a Kinematic body. Does this body discourage the use of MovePosition to handle moving the player?

    I used MovePosition to be able to move the Player in 8 directions seamlessly. I can switch out the movement with another piece of code if that works better. If MovePosition still works in this instance then I could use that to be applied to the roll input, but would that require moving the Movement out of Fixed Update?

    Thank you, much appreciate your help.

    SuperHyperHedgey

     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,321
    No but it's also odd and more specialized to use it because if you think about it, you're asking to move to a specific position but it might not get there if it hits something. Also, gravity cannot correctly take affect if it's trying to move to a position so doing this constantly means you need to set its gravity scale to zero and add the gravity term into the position you want to move to. This is how you'd do it with a Kinematic body. In the end, you have to understand what MovePosition is doing and consider what the other features of a Dynamic body are such as gravity, forces or you setting the velocity; none of those can work if you're tying to get to a specific position that simulation step. For Kinematic, none of these really matter.

    I'm not following. When you ask for a MovePosition to happen, it is actioned in the next simulation step. If that's the default time (during FixedUpdate) then it'll move then.