void Move()
    {
        if (inCutscene)
        {
            anim.SetFloat("Speed", 0f);
            if (grounded)
            {
                rb2d.velocity = Vector2.zero;
            }
            anim.SetFloat("VerticalInput", 0f);
            anim.SetBool("HorizontalInput", false);
            anim.SetFloat("VerticalSpeed", 0f);
            return;
        }

        anim.SetBool("HorizontalInput", InputManager.HasHorizontalInput());
        anim.SetFloat("VerticalSpeed", rb2d.velocity.y);

        if (InputManager.ButtonDown(Buttons.JUMP) && supercruise)
        {
            EndSupercruise();
        }

        if (!grounded && rb2d.velocity.y < 0 && groundCheck.TouchingPlatforms() != null && rb2d.velocity.y > 0)
        {
            LedgeBoost();
        }

        if (supercruise && !grounded && !touchingWall && !MovingForwards() && InputManager.HorizontalInput() != 0)
        {
            Airbrake();
            return;
        }

        if (supercruise && rb2d.velocity.x == 0)
        {
            InterruptSupercruise();
        }

        if (!frozen && !(stunned || dead))
        {
            if (InputManager.VerticalInput() < 0 && InputManager.ButtonDown(Buttons.JUMP))
            {
                EdgeCollider2D[] platforms = groundCheck.TouchingPlatforms();
                if (platforms != null && grounded)
                {
                    DropThroughPlatforms(platforms);
                }
            }

            anim.SetBool("InputBackwards", InputBackwards());

            float modifier = IsForcedWalking() ? 0.4f : 1f;
            float hInput   = InputManager.HorizontalInput() * modifier;
            // you can't push forward + down on sticks, so do this
            if (hInput >= 0.5f)
            {
                hInput = 1f;
            }
            if (!touchingWall && !wallCheck.TouchingLedge())
            {
                anim.SetFloat("Speed", Mathf.Abs(hInput));
            }
            else if (IsFacing(touchingWall) && MovingForwards())
            {
                anim.SetFloat("Speed", 0);
            }

            if (InputManager.HorizontalInput() != 0)
            {
                float xVec = hInput * moveSpeed;
                if (IsSpeeding() && MovingForwards())
                {
                    xVec = rb2d.velocity.x;
                }
                rb2d.velocity = (new Vector2(
                                     xVec,
                                     rb2d.velocity.y)
                                 );
                movingRight = InputManager.HorizontalInput() > 0;
            }

            //if they've just started running
            if (!runningLastFrame && rb2d.velocity.x != 0 && grounded && Mathf.Abs(hInput) > 0.6f && !IsFacing(touchingWall))
            {
                int scalar = rb2d.velocity.x > 0 ? 1 : -1;
                if (scalar * ForwardScalar() > 0)
                {
                    BackwardDust();
                }
                else
                {
                    ForwardDust();
                }
                HairBackwards();
            }

            runningLastFrame = Mathf.Abs(hInput) > 0.6f;
        }

        if (supercruise)
        {
            float maxV = Mathf.Max(Mathf.Abs(superCruiseSpeed), Mathf.Abs(rb2d.velocity.x)) * ForwardScalar();
            rb2d.velocity = new Vector2(maxV, 0);
        }

        if (rb2d.velocity.y < terminalSpeed)
        {
            terminalFalling = true;
            rb2d.velocity   = new Vector2(rb2d.velocity.x, terminalSpeed);
        }
        else
        {
            terminalFalling = false;
        }

        if (rb2d.velocity.y < hardLandSpeed && !inMeteor)
        {
            hardFalling = true;
            anim.SetBool("FastFalling", true);
        }
        else if (!IsGrounded())
        {
            hardFalling = false;
            anim.SetBool("FastFalling", false);
        }

        if (wallCheck.TouchingLedge() && InputManager.HasHorizontalInput() && rb2d.velocity.y > 0)
        {
            LedgeBoost();
        }

        if (touchingWall && !grounded && !InputManager.HasHorizontalInput())
        {
            rb2d.velocity = new Vector2(0, rb2d.velocity.y);
        }

        movingForwardsLastFrame = MovingForwards();

        // due to frame skips or other weird shit, add a little self-healing here
        if (!grounded && rb2d.velocity.y == 0f && !supercruise)
        {
            Invoke("HealGroundTimeout", 0.5f);
        }
        else if (grounded || (!grounded && rb2d.velocity.y != 0f) || supercruise)
        {
            CancelInvoke("HealGroundTimeout");
        }
    }
    void Move()
    {
        if (inCutscene)
        {
            anim.SetFloat("Speed", 0f);
            if (grounded)
            {
                rb2d.velocity = Vector2.zero;
            }
            anim.SetFloat("VerticalInput", 0f);
            return;
        }

        anim.SetBool("HorizontalInput", HorizontalInput());

        if (Input.GetButtonDown("Jump") && supercruise)
        {
            EndSupercruise();
        }

        if (supercruise && !MovingForwards() && Input.GetAxis("Horizontal") != 0)
        {
            Airbrake();
            return;
        }

        if (Input.GetButtonDown("Special") && HorizontalInput() && (!frozen || justLeftWall) && Input.GetAxis("Vertical") >= -0.1)
        {
            if (unlocks.HasAbility(Ability.Dash))
            {
                Dash();
            }
        }

        if (frozen)
        {
            anim.SetFloat("Speed", 0f);
            if (grounded)
            {
                rb2d.velocity = Vector2.zero;
            }
        }

        if (!frozen && !(stunned || dead))
        {
            if (Input.GetAxis("Vertical") < 0 && grounded && !backstepCooldown && Input.GetButtonDown("Attack"))
            {
                Backstep();
            }
            if (Input.GetAxis("Vertical") < 0 && Input.GetButtonDown("Jump"))
            {
                if (GetComponent <GroundCheck>().TouchingPlatform() && grounded)
                {
                    DropThroughPlatform();
                }
            }

            float modifier = IsForcedWalking() ? 0.4f : 1f;
            float hInput   = Input.GetAxis("Horizontal") * modifier;
            if (!touchingWall && !wallCheck.TouchingLedge() && !midSwing)
            {
                anim.SetFloat("Speed", Mathf.Abs(hInput));
            }
            else
            {
                anim.SetFloat("Speed", 0);
            }
            anim.SetFloat("VerticalSpeed", rb2d.velocity.y);

            if (HorizontalInput() && !midSwing)
            {
                if (Input.GetAxis("Horizontal") != 0)
                {
                    //if they just finished a dash or supercruise, keep their speed around for a bit ;^)
                    if (IsSpeeding() &&
                        (Input.GetAxis("Horizontal") * GetForwardScalar() > 0))
                    {
                        //slow the player down less in the air
                        float divisor = 1.01f;
                        if (!grounded)
                        {
                            divisor = 1.005f;
                        }
                        rb2d.velocity = new Vector2(
                            x: rb2d.velocity.x / divisor,
                            y: rb2d.velocity.y
                            );
                    }
                    else
                    {
                        rb2d.velocity = new Vector2(x: (hInput * maxMoveSpeed), y: rb2d.velocity.y);
                    }
                    movingRight = Input.GetAxis("Horizontal") > 0;
                }
                if (!runningLastFrame && rb2d.velocity.x != 0 && grounded && Mathf.Abs(hInput) > 0.6f && !touchingWall)
                {
                    int scalar = rb2d.velocity.x > 0 ? 1 : -1;
                    if (scalar * GetForwardScalar() > 0)
                    {
                        BackwardDust();
                    }
                    else
                    {
                        ForwardDust();
                    }
                }
            }
            //if no movement, stop the player on the ground
            else if (grounded)
            {
                rb2d.velocity = new Vector2(x: 0, y: rb2d.velocity.y);
                if (runningLastFrame && !touchingWall && !midSwing)
                {
                    ForwardDust();
                }
            }
            //or slow them down in the air if they haven't just walljumped
            else
            {
                rb2d.velocity = new Vector2(
                    x: rb2d.velocity.x / 1.01f,
                    y: rb2d.velocity.y
                    );
            }

            //if they're above max move speed, gently slow them
            if (IsSpeeding() && !IsForcedWalking())
            {
                rb2d.velocity = new Vector2(
                    x: rb2d.velocity.x / 1.01f,
                    y: rb2d.velocity.y
                    );
            }

            runningLastFrame = Mathf.Abs(hInput) > 0.6f;
        }

        if (dashing)
        {
            rb2d.velocity = new Vector2((dashSpeed + preDashSpeed) * GetForwardScalar(), 0);
        }

        else if (supercruise)
        {
            rb2d.velocity = new Vector2((superCruiseSpeed + preDashSpeed) * GetForwardScalar(), 0);
        }

        if (rb2d.velocity.y < terminalVelocity)
        {
            terminalFalling = true;
            rb2d.velocity   = new Vector2(rb2d.velocity.x, terminalVelocity);
        }
        else
        {
            terminalFalling = false;
        }

        if (rb2d.velocity.y < hardLandVelocity)
        {
            hardFalling = true;
        }
        else
        {
            hardFalling = false;
        }

        if (wallCheck.TouchingLedge() && !grounded)
        {
            LedgeBoost();
        }

        if (touchingWall && !grounded && !HorizontalInput())
        {
            rb2d.velocity = new Vector2(0, rb2d.velocity.y);
        }
    }
    void Move()
    {
        if (inCutscene)
        {
            anim.SetFloat("Speed", 0f);
            if (grounded)
            {
                rb2d.velocity = Vector2.zero;
            }
            anim.SetFloat("VerticalInput", 0f);
            anim.SetBool("HorizontalInput", false);
            anim.SetFloat("VerticalSpeed", 0f);
            return;
        }

        anim.SetBool("HorizontalInput", InputManager.HasHorizontalInput());
        anim.SetFloat("VerticalSpeed", rb2d.velocity.y);

        if (InputManager.ButtonDown(Buttons.JUMP) && supercruise)
        {
            EndSupercruise();
        }

        if (supercruise && !grounded && !touchingWall && !MovingForwards() && InputManager.HorizontalInput() != 0)
        {
            Airbrake();
            return;
        }

        if (supercruise && rb2d.velocity.x == 0)
        {
            InterruptSupercruise();
        }

        if (InputManager.Button(Buttons.SPECIAL) && InputManager.HasHorizontalInput() && (!frozen || justLeftWall) && Mathf.Abs(InputManager.VerticalInput()) <= 0.2f)
        {
            if (unlocks.HasAbility(Ability.Dash))
            {
                Dash();
            }
        }

        if (!movingForwardsLastFrame && MovingForwards() && !missedParry)
        {
            StartParryWindow();
            missedParry = true;
            Invoke("EndMissedParryWindow", missedInputCooldown);
        }

        if (!frozen && !(stunned || dead))
        {
            if (InputManager.VerticalInput() < 0 && InputManager.ButtonDown(Buttons.JUMP))
            {
                EdgeCollider2D platform = GetComponent <GroundCheck>().TouchingPlatform();
                if (platform != null && grounded)
                {
                    DropThroughPlatform(platform);
                }
            }

            anim.SetBool("InputBackwards", InputBackwards());

            float modifier = IsForcedWalking() ? 0.4f : 1f;
            float hInput   = InputManager.HorizontalInput() * modifier;
            if (!touchingWall && !wallCheck.TouchingLedge())
            {
                anim.SetFloat("Speed", Mathf.Abs(hInput));
            }
            else if (IsFacing(touchingWall) && MovingForwards())
            {
                anim.SetFloat("Speed", 0);
            }

            if (InputManager.HorizontalInput() != 0)
            {
                float xVec = hInput * moveSpeed;
                if (IsSpeeding() && MovingForwards())
                {
                    xVec = rb2d.velocity.x;
                }
                rb2d.velocity = (new Vector2(
                                     xVec,
                                     rb2d.velocity.y)
                                 );
                movingRight = InputManager.HorizontalInput() > 0;
            }

            //if they've just started running
            if (!runningLastFrame && rb2d.velocity.x != 0 && grounded && Mathf.Abs(hInput) > 0.6f && !IsFacing(touchingWall))
            {
                int scalar = rb2d.velocity.x > 0 ? 1 : -1;
                if (scalar * ForwardScalar() > 0)
                {
                    BackwardDust();
                }
                else
                {
                    ForwardDust();
                }
                HairBackwards();
            }

            runningLastFrame = Mathf.Abs(hInput) > 0.6f;
        }

        if (dashing)
        {
            rb2d.velocity = new Vector2(
                ForwardScalar() * (dashSpeed + preDashSpeed),
                Mathf.Max(rb2d.velocity.y, 0)
                );
        }
        else if (supercruise)
        {
            float maxV = Mathf.Max(Mathf.Abs(superCruiseSpeed), Mathf.Abs(rb2d.velocity.x)) * ForwardScalar();
            rb2d.velocity = new Vector2(maxV, 0);
        }

        if (rb2d.velocity.y < terminalSpeed)
        {
            terminalFalling = true;
            rb2d.velocity   = new Vector2(rb2d.velocity.x, terminalSpeed);
        }
        else
        {
            terminalFalling = false;
        }

        if (rb2d.velocity.y < hardLandSpeed && !inMeteor)
        {
            hardFalling = true;
            anim.SetBool("FastFalling", true);
        }
        else if (!IsGrounded())
        {
            hardFalling = false;
            anim.SetBool("FastFalling", false);
        }

        if (wallCheck.TouchingLedge() && !grounded)
        {
            LedgeBoost();
        }

        if (touchingWall && !grounded && !InputManager.HasHorizontalInput())
        {
            rb2d.velocity = new Vector2(0, rb2d.velocity.y);
        }

        movingForwardsLastFrame = MovingForwards();
    }