Dashing in Unity 2D Top-Down Projects

47 views Asked by At

So in 3D games I've used .AddForce(dashForce, ForceMode.Impulse) in order to calculate and execute the Dash-Function (and it worked like a charm). However, as I translated everything I knew into the 2D-world (so a Vector2 dashForce and using ForceMode2D) something isnt working correctly.


    public class NewBehaviourScript : MonoBehaviour
    {
        [Header ("Running Values and bools")]
        private float vertical;
        private float horizontal;
        private float speed = 10f;
        private bool isFacingRight = true;

        [Header("Sprint")]
        private bool canSprint = true;
        public float sprintFactor = 5f;
        

        [SerializeField] private Rigidbody2D rb;
        [SerializeField] private Transform groundCheck;
        [SerializeField] private LayerMask hakenCheck;
        [SerializeField] private LayerMask groundLayer;


        [Header("Dash Mechanic")]
        private bool canDash = true;
        private bool isDashing = false;
        public float DashCoolDown = 1f;
        public float DashDuration = 1f;
        private float DashFactorFront = 8f;
        
        [SerializeField] TrailRenderer tr;

        private void Start()
        {
            rb = GetComponent<Rigidbody2D>();
           
        }

        void Update()
        { 

            if (canDash && !isDashing && Input.GetKey(KeyCode.C))
            {
                StartCoroutine(Dash());
            }

        }

        private void FixedUpdate()
        {
            float horizontal = Input.GetAxisRaw("Horizontal");
            float vertical = Input.GetAxisRaw("Vertical");

            rb.velocity = new Vector2(horizontal, vertical).normalized * speed;

               //sprinting - tr emitting
            if (canSprint == true && Input.GetKey(KeyCode.LeftShift))
            {
                rb.velocity = new Vector2(horizontal, vertical).normalized * speed * sprintFactor ;
                

            }

        }

        private IEnumerator Dash()
        {
            Debug.Log("Dash");
            canDash = false;
            isDashing = true;

            if (rb.velocity.x > rb.velocity.y || rb.velocity.x == rb.velocity.y)
            {
                Vector2 dashForce = rb.transform.right * DashFactorFront;
                rb.AddForce(dashForce, ForceMode2D.Impulse);

                yield return new WaitForSeconds(DashDuration);
                isDashing = false;
                yield return new WaitForSeconds(DashCoolDown);
                canDash = true;
            }
            else if (rb.velocity.y > rb.velocity.x)
            {
                Vector2 dashForce = rb.transform.up * DashFactorFront;
                rb.AddForce(dashForce, ForceMode2D.Impulse);

                yield return new WaitForSeconds(DashDuration);
                isDashing = false;
                yield return new WaitForSeconds(DashCoolDown);
                canDash = true;
            }
        }
     
        }

So what I know so far is that the coroutine gets executed (checked by testing with a Debug.Log message && also the cooldown I've implemented works). Hence, it seems like that the dash function / calculation has a problem / I had a wrong idea. I even tried out using different ForceModes, even though I recognized that there seems to be just "force" and "impulse" (none of those worked for me).

One thing I think is possible is that I have to use a empty as a child of the player inside the player and apply the force to the empty itself, however, this also havent worked out yet even though I tried it twice with different empty objects. So, in the end I stay clueless where this issue is based on. In the solution that I've provided I just went back to using the RigidBody as the source of the used axis (x,y) and applied the force to them.

1

There are 1 answers

0
Will Lacey On

In FixedUpdate you are directly setting the Rigidbody's velocity which undoes any force setting that you would be doing in Dash. By the looks of it you are trying to clamp the max velocity the Rigidbody can move, try this by calling:

rb.velocity = Vector2.ClampMagnitude(rb.velocity, YOUR_MAX_SPEED);

instead of what you have:

rb.velocity = new Vector2(horizontal, vertical).normalized * speed;

As an aside you are also not using your fields vertical, horizontal, and isFacingRight at all. Currently you have:

float horizontal = Input.GetAxisRaw("Horizontal");
float vertical = Input.GetAxisRaw("Vertical");

which will freeze the player in the air if they are falling or shoved by another RigidBody/Collider2D.

Hope this helps!