private void FixedUpdate()
    {
        if (IsDead)
        {
            var bigBlackColor = _bigBlack.color;
            bigBlackColor.a += Time.fixedDeltaTime;
            _bigBlack.color  = bigBlackColor;
            if (bigBlackColor.a >= 0.99f)
            {
                SceneManager.LoadSceneAsync(SceneManager.GetActiveScene().name);
            }
            return;
        }



        // Check if should kill
        if (Health <= 0 || transform.position.y < -9f || Input.GetButtonDown("Restart"))
        {
            IsDead = true;
            return;
        }



        if (_hurtTimer > 0.01f)
        {
            _inputDirX = 0;
        }

        Health -= HealthDecrementAmount * Time.fixedDeltaTime;

        // Store relative velocity of whatever is being stood on
        _relativeVelocity = new Vector2();
        Rigidbody2D objectBeingStoodOn = null;

        // Store force vector that can be used later
        var pendingForceVector = new Vector2();

        // Handle stomping on things
        foreach (var col in _groundCheck.GetOverlappingColliders())
        {
            // Generic rigidbody check
            var otherRb = col.gameObject.GetComponent <Rigidbody2D>();
            if (otherRb != null)
            {
                objectBeingStoodOn = otherRb;
                _relativeVelocity  = otherRb.velocity;
            }

            // Shy guy check
            var shyGuy = col.gameObject.GetComponent <ShyGuy>();
            if (shyGuy != null)
            {
                // Kill ShyGuy
                if (!shyGuy.IsDead && _hurtTimer < 0.1f)
                {
                    // Force jump (lil' trick)

                    if (_flutterJumpTimer > 0.0f)
                    {
                        _flutterJumpTimer = 0.0f;
                    }
                    _jumpButtonLeewayTimer = 0.1f;
                    // Shitton of effects
                    PlaySound("punch");
                    PlaySound("hit");
                    PlayParticleEffect("white_hit", shyGuy.transform.position);
                    PlayParticleEffect("red_hit", shyGuy.transform.position);
                    _cameraController.StartScreenShake(0.8f, 0.4f);
                    shyGuy.Kill();
                }
            }
        }


        var is_braking = false;

        // Determine if braking
        // If input direction is different from the last x speed direction, the player is braking.
        if ((int)Mathf.Sign(_xSpd) != (int)Mathf.Sign(_inputDirX) || _inputDirX == 0)
        {
            is_braking       = true;
            _speedRampUpTime = 0f;
        }

        var movementSpdModifier = 1.0f;
        var rampUp = Mathf.Clamp(_speedRampUpTime, 0.1f, 1f);

        if (_flutterJumpTimer <= 0.0f)
        {
            _speedRampUpTime += _accelSpd * Time.fixedDeltaTime;
        }
        else
        {
            _speedRampUpTime += 0.5f * _accelSpd * Time.fixedDeltaTime;
        }

        _xSpd = _inputDirX * rampUp * _movementSpd;

        // Handle jumping
        var canJump = CanJump();

        // Jump if jump button is pressed within leeway amount
        if (_jumpButtonLeewayTimer > 0.0f && canJump)
        {
            _rb.velocity = new Vector2(_rb.velocity.x, 0.0f);
            _rb.AddForce(_jumpHeightImpulse * Vector2.up, ForceMode2D.Impulse);
            _jumpSafetyTimer = JumpSafetyTimerTime;
            // Reset flutter jump count
            _flutterJumpsBeforeLandingCount = 0;

            // Also play jump sound
            PlaySound("yoshi_jump");
        }

        if (_isJumpHeldDown)
        {
            if (_jumpHoldTime < 0.0f)
            {
                _jumpHoldTime = 0.0f;
            }
            _jumpHoldTime += Time.fixedDeltaTime;
        }
        else if (_isJumpJustReleased || CanJump())
        {
            _jumpHoldTime = -1.0f;
        }

        if (_isJumpJustReleased)
        {
            //_rb.velocity = new Vector2(_rb.velocity.x, 0.0f);
            _rb.AddForce(_fastFallImpulse * Vector2.down, ForceMode2D.Impulse);
        }

        // Handle flutter jump

        // If Yoshi is falling and jump is held down...
        if ((_jumpButtonLeewayTimer > 0.0f ||
             (_isJumpHeldDown && _flutterJumpsBeforeLandingCount < 1) && _rb.velocity.y < -0.5f) &&
            _rb.velocity.y < -0.05f)
        {
            _flutterJumpIncidentYVelocity = _rb.velocity.y;
            _flutterJumpsBeforeLandingCount++;
            // If not already flutter jumping and cooldown is not active, make Yoshi flutter jump
            if (_flutterJumpTimer <= 0.0f && _flutterJumpCooldownTimer <= 0.0f)
            {
                _flutterJumpTimer = FlutterJumpTimerTime;
                // Also play flutter jump sound
                Invoke(nameof(PlayFlutterSound), 0.3f);
            }
        }

        if (!_isJumpHeldDown && _flutterJumpTimer > 0.2f)
        {
            _flutterJumpTimer = 0.1f;
        }


        // Do flutter jump stuff if flutter jumping
        if (_flutterJumpTimer > 0.0f)
        {
            var mod = 1.0f;
            if (_flutterJumpsBeforeLandingCount > 1)
            {
                mod = 0.5f;
            }

            var YVelocityChange = _flutterJumpAmount *
                                  (1.15f * (Mathf.Sin(2 * (_flutterJumpTimer) * Mathf.PI + 0.25f) + 0.2f * mod) +
                                   0.2f * mod);
            _rb.velocity = new Vector2(_rb.velocity.x,
                                       (0.7f * _flutterJumpIncidentYVelocity) + YVelocityChange + _gravitySpd);
            _flutterJumpCooldownTimer = FlutterJumpCooldownTimerTime;

            movementSpdModifier *= 0.55f;
        }

        if (Input.GetButton("Tongue") && GetComponentInChildren <Tongue>().TongueTime <= 0.25f && !CanJump())
        {
            movementSpdModifier *= 0.5f;
        }

        // Handle movement
        var newVelocity = _rb.velocity;

        newVelocity.x = _xSpd * movementSpdModifier;

        if (_inputDirX == 0 && Mathf.Abs(_rb.velocity.x) > 0.15f)
        {
            newVelocity.x = (_rb.velocity.x - _relativeVelocity.x) * 0.9f;
        }

        newVelocity.y -= _gravitySpd;

        // Add relative x velocity of whatever is being stood on
        newVelocity.x += _relativeVelocity.x;

        _rb.velocity = newVelocity;

        // Normalise rotation in the air
        if (_jumpHoldTime > 0.0f)
        {
            _rb.rotation = Mathf.Lerp(_rb.rotation, 0f, 0.4f);
        }


        // Prevent falling into the ground too much when not moving
        if (Math.Abs(newVelocity.x) < 0.5f && _inputDirX == 0 && _jumpButtonLeewayTimer <= 0.0f &&
            _flutterJumpTimer <= 0.0f && IsGrounded())
        {
            _rb.velocity = new Vector2(0f, _rb.velocity.y);
        }

        // Limit falling velocity
        if (_rb.velocity.y < -10f)
        {
            _rb.velocity = new Vector2(_rb.velocity.x, -10f);
        }

        _rb.velocity     += _knockbackVector;
        _knockbackVector *= 0.9f;

        // Clamp rotation
        _rb.angularVelocity = Mathf.Clamp(_rb.angularVelocity, -100f, 100f);
        _rb.rotation        = Mathf.Clamp(_rb.rotation, -20f, 20f);


        HandleTimers();
    }