private void HandleMovement()
        {
            if (IsGrounded)
            {
                _velocity.y = 0;
                _numJumps   = 0;
            }

            if (CanMove)
            {
                float horizontalMovement = CharacterYoke.Movement.x;

                if ((_numJumps < MaxJumps || IsGrounded) && !CharacterYoke.Jump)
                {
                    _jumpAvailable = _config.JumpHeight;
                    _canJump       = true;
                }

                // we can only jump whilst grounded
                if (_canJump && CharacterYoke.Jump && _jumpAvailable > 0.0f)
                {
                    if (CharacterYoke.GetButtonDown(InputAction.Jump))
                    {
                        _jumpStartTime = Time.time;
                        _numJumps++;
                    }

                    float jumpThisFrame = _config.GetJumpSpeed(Time.time - _jumpStartTime) * Time.deltaTime;
                    _jumpAvailable -= jumpThisFrame;
                    _velocity.y     = Mathf.Sqrt(2f * jumpThisFrame * -_config.Gravity);
                }
                else
                {
                    // apply gravity before moving
                    _velocity.y += _config.Gravity * Time.deltaTime;
                }

                if (CharacterYoke.GetButtonUp(InputAction.Jump))
                {
                    _canJump = false;
                }

                _velocity.x = horizontalMovement * _config.RunSpeed * RunSpeedModifier;

                // if holding down bump up our movement amount and turn off one way platform detection for a frame.
                // this lets us jump down through one way platforms
                if (IsGrounded && CharacterYoke.GetButtonDown(InputAction.Drop))
                {
                    _velocity.y *= 3f;
                    IgnoreOneWayPlatformsThisFrame = true;
                }
            }
            else
            {
                _velocity.x = 0.0f;
            }

            _velocity = MoveBy(_velocity, _velocity * Time.deltaTime);
        }
        private void HandleAttacking()
        {
            if (CanMeleeAttack() && CharacterYoke.GetButtonDown(InputAction.MeleeAttack))
            {
                StartCoroutine(MeleeAttack());
            }

            if (CanRangedAttack() && CharacterYoke.GetButtonDown(InputAction.RangedAttack))
            {
                StartCoroutine(RangedAttack());
                _lastRangedAttackTime = Time.time;
            }

            if (CanDashAttack() && CharacterYoke.GetButtonDown(InputAction.DashAttack))
            {
                StartCoroutine(DashAttack());
            }
        }