Player animation: Ducking movement stop any other movement

Hi! I’m working on a 2D platformer and the script for player’s movement. Player has a lot of movement, like moving left and right, jumping, falling through platform. It also has rolling when pressing S key down - the key for ducking - and a movement key - A or D - at the same time.

However, I’m facing an issue I cannot fix:

  • Upon pressing S key down while player is running - so A or D are pressed down - the player start ducking but keeps moving left or right in the ducking position awkwardly. How to make sure that player stop all movement it was previously doing when pressing S key down for ducking? As well as making sure it would stay ducked while continuously pressing S key down?

Here is the script for my player’s movement in case it helps

Please let me know if you have any tips on how to fix this issue.
Many thanks!

public class NewBehaviourScript : MonoBehaviour
{
    public float speed = 5f;
    public float jumpSpeed = 8f;
    public float rollSpeed = 8f; // Speed during roll
    public float rollDuration = 0.3f; // Duration of roll effect
    private float direction = 0f;
    private Rigidbody2D player;

    public Transform groundCheck;
    public float groundCheckRadius;
    public LayerMask groundLayer;
    private bool isTouchingGround;

    private Animator playerAnimation;
    [SerializeField] private Collider2D playerCollider;

    // Add variables for ducking and rolling
    private bool isDucking = false;
    private bool isRolling = false;

    private float rollTime = 0.5f; // Timer for roll duration

    // Add a variable to check for platform tags
    private GameObject currentPlatform;

    // Track if the player is dropping through the platform
    private bool isDroppingThrough = false;

    // Start is called before the first frame update
    void Start()
    {
        player = GetComponent<Rigidbody2D>();
        playerAnimation = GetComponent<Animator>();
        playerCollider = GetComponent<Collider2D>(); // Get the player's collider
    }

    // Update is called once per frame
    void Update()
    {
        // Check if the player is on the ground
        isTouchingGround = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer);
        direction = Input.GetAxis("Horizontal");

        // Handle rolling logic
        if (isRolling)
        {
            rollTime += Time.deltaTime;
            if (rollTime >= rollDuration)
            {
                // Stop rolling after the duration
                isRolling = false;
                playerAnimation.SetBool("Roll", false);
                player.velocity = new Vector2(0, player.velocity.y); // Stop movement
                playerAnimation.SetFloat("Speed", 0f); // Ensure idle animation
            }
            else
            {
                // Move the player in the direction it's facing
                player.velocity = new Vector2(rollSpeed * Mathf.Sign(transform.localScale.x), player.velocity.y);
            }
        }
        else
        {
            // Move the player left or right (only if not ducking or rolling)
            if (!isDucking)
            {
                if (direction > 0f)
                {
                    player.velocity = new Vector2(direction * speed, player.velocity.y);
                    transform.localScale = new Vector2(3.751758f, 3.751758f);
                }
                else if (direction < 0f)
                {
                    player.velocity = new Vector2(direction * speed, player.velocity.y);
                    transform.localScale = new Vector2(-3.751758f, 3.751758f);
                }
                else
                {
                    player.velocity = new Vector2(0, player.velocity.y);
                }
            }
            else
            {
                // If ducking, stop horizontal movement
                player.velocity = new Vector2(0, player.velocity.y);
            }

            // Jump logic (allow jumping from ducking)
            if (Input.GetButtonDown("Jump") && isTouchingGround)
            {
                if (isDucking)
                {
                    // Reset ducking state and animation
                    playerAnimation.SetBool("Duck", false);
                    isDucking = false;
                }
                // Set jump velocity
                player.velocity = new Vector2(player.velocity.x, jumpSpeed);
                playerAnimation.SetTrigger("Jump");
            }
        }

        // Update Animator Parameters
        playerAnimation.SetFloat("Speed", Mathf.Abs(player.velocity.x));
        playerAnimation.SetBool("OnGround", isTouchingGround);
        playerAnimation.SetBool("Duck", isDucking);
        playerAnimation.SetBool("Roll", isRolling);

        // Ducking and drop through platform logic
        if (Input.GetKeyDown(KeyCode.S) && isTouchingGround && !isRolling)
        {
            playerAnimation.SetBool("Duck", true);
            isDucking = true;

            // Drop through platform if player is on a platform
            if (currentPlatform != null && currentPlatform.CompareTag("Platform") && !isDroppingThrough)
            {
                StartCoroutine(DropThroughPlatform());
            }
        }
        else if (Input.GetKeyUp(KeyCode.S) && isDucking)
        {
            playerAnimation.SetBool("Duck", false);
            isDucking = false;
        }

        // Handle Roll Input
        if (Input.GetKey(KeyCode.S) && Mathf.Abs(direction) > 0f && isTouchingGround && !isRolling)
        {
            // Start rolling: set animation and adjust speed
            playerAnimation.SetBool("Roll", true);
            isRolling = true;
            rollTime = 0f; // Reset roll timer
            player.velocity = new Vector2(rollSpeed * Mathf.Sign(transform.localScale.x), player.velocity.y);

            // Flip the character's sprite depending on the direction of the roll
            transform.localScale = new Vector2(direction > 0f ? 3.751758f : -3.751758f, 3.751758f);
        }

        // Handle fall animation
        if (player.velocity.y < -0.1f && !isTouchingGround)
        {
            playerAnimation.SetTrigger("Fall");
        }
        else if (isTouchingGround)
        {
            playerAnimation.ResetTrigger("Fall");
            playerAnimation.SetBool("Jump", false); // Reset jump after landing
        }
    }

    // Detect if the player is on a platform by using tags
    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Platform"))
        {
            currentPlatform = collision.gameObject;
        }
    }

    private void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Platform"))
        {
            currentPlatform = null;
        }
    }

    // Coroutine to drop through platform by temporarily disabling collision between player and platform
    private IEnumerator DropThroughPlatform()
    {
        Collider2D platformCollider = currentPlatform.GetComponent<CompositeCollider2D>();

        Physics2D.IgnoreCollision(playerCollider, platformCollider, true); // Disable collision with the platform
        yield return new WaitForSeconds(1f); // Adjust the delay as necessary
        Physics2D.IgnoreCollision(playerCollider, platformCollider, false); // Re-enable collision
    }
}