Coyote time and jump buffering: the twelve lines of a good jump
When players say "the jump doesn't feel good", they usually mean two missing features. Both take half an hour to write.
What the problem looks like
Everyone who playtests your platformer prototype says the same thing: "the jump feels off". Nobody can tell you exactly what is wrong. The code is correct: if you are touching the ground, jump; if not, don't.
The problem is not in the code, it is in the human. The player presses the button the moment they notice they have walked off the ledge — but by then it is too late. And when they press jump mid-air, they expect to jump the instant they land.
Two small tolerance windows
Coyote time keeps the right to jump open for a short while after the character leaves the ground. The name comes from the cartoon coyote who runs off a cliff and hangs in the air for a beat.
Jump buffering works in the opposite direction: if the player pressed the button just before landing, that press is remembered and applied the instant they touch down.
What the values should be
In the projects I have measured, both windows work well between 100 and 150 ms — six to nine frames at 60 FPS. Shorter and the effect is imperceptible; longer and the character looks like it is jumping off thin air.
Do not hard-code these numbers. Put them in a ScriptableObject or a data table; a designer must be able to change them without launching the game.
How far it goes
The same logic pays off everywhere else: buffering attack input, double-jump tolerance, the ledge-grab catch window, even the key queue in menu transitions.
The general rule: when the player's intent conflicts with the game's rules, rule in the player's favour. Games that do this are the ones described as "responsive".