private bool _jumpToConsume; private bool _bufferedJumpUsable; private bool _endedJumpEarly; private bool _coyoteUsable; private float _timeJumpWasPressed; private bool HasBufferedJump => _bufferedJumpUsable && _time < _timeJumpWasPressed + _stats.JumpBuffer; private bool CanUseCoyote => _coyoteUsable && !_grounded && _time < _frameLeftGrounded + _stats.CoyoteTime; private void HandleJump() { if (!_endedJumpEarly && !_grounded && !_frameInput.JumpHeld && _rb.velocity.y > 0) _endedJumpEarly = true; if (!_jumpToConsume && !HasBufferedJump) return; if (_grounded || CanUseCoyote) ExecuteJump(); _jumpToConsume = false; } private void ExecuteJump() { _endedJumpEarly = false; _timeJumpWasPressed = 0; _bufferedJumpUsable = false; _coyoteUsable = false; _frameVelocity.y = _stats.JumpPower; Jumped?.Invoke(); }