| Engine | Unity 2022.3 LTS or newer |
|---|---|
| Language | C# |
| Time to run | ~3 minutes |
| Level | Intermediate — comfortable with Rigidbody2D and ground checks |
| Output | One file (~110 lines) |
| Dependencies | None. No packages. |
The prompt
Open a fresh chat at claude.ai/new, paste, and send.
$ Build me a Unity 2022.3+ 2D platformer player controller with coyote time, jump buffer, and variable jump height. // shape - Single C# MonoBehaviour, file PlatformerController.cs. - No external packages, no input system package. - Requires Rigidbody2D, BoxCollider2D, and a serialized Transform groundCheck child. // movement - Horizontal: A/D or Left/Right, normalized speed. - Speed: [SerializeField] float, default 7. - Acceleration / deceleration: smooth out velocity changes (use a SerializeField smoothing constant, default 0.06). // jump feel - Coyote time: 0.1s grace window. Player can jump for that long after walking off a ledge. - Jump buffer: 0.1s. If player presses jump just before landing, register it on landing. - Variable jump height: if jump button is released before peak, cut velocity.y by 50% (configurable). - Jump force: [SerializeField] float, default 14. // ground check - Use Physics2D.OverlapCircle on the groundCheck Transform with a small radius (0.15) and a SerializeField LayerMask called groundLayer. - Update isGrounded once per FixedUpdate. // constraints - Read input in Update, apply physics in FixedUpdate. - Coyote time and jump buffer are tracked with a single timer field each, decremented in Update. - No magic numbers. Everything tunable is SerializeField. // return format - One file. No prose before or after the code. - Brief comments only on the coyote-time and jump-buffer mechanics, since they're the non-obvious bit.
What this gets you
The difference between "this platformer is unplayable" and "this platformer feels good." Coyote time and jump buffer are the two single biggest "game feel" features a platformer can have, and most tutorials skip them because they're not strictly required for the character to move. They are required for the character to feel like a character.
Variable jump height is the third thing every commercial platformer has. Together, these three are the floor — not a polish layer.
Skip the copy-paste — download the starter pack
If watching the prompt-output go in script-by-script feels slow, grab the pre-tested zip instead. Two files: the controller script + an Editor utility that creates a fully-wired Player GameObject in your scene with one menu click. Drop into your Unity project, hit Pixeldex → Spawn Platformer Player, press Play. CC0, no attribution required.
Why these three matter
Coyote time
Without coyote time, when a player runs off the edge of a platform and presses jump 1 frame too late, the jump is silently swallowed. The player perceives this as "the game ate my input." With a 0.1s grace window after leaving the ground, the jump still registers and the platformer feels responsive instead of unforgiving.
Jump buffer
The flip side. If the player presses jump just before they land, without a buffer the input is lost. With a 0.1s lookback window, the press is remembered and consumed the moment they touch ground. This is what makes "press jump as I land to chain a second jump" feel possible.
Variable jump height
Holding the button gives a longer jump; tapping it gives a shorter one. Without this, every jump is full-height and platforming feels rigid. The implementation is one line: if the player releases jump while velocity.y is still positive, multiply velocity.y by 0.5.
What good output looks like
- Two timer fields, decremented in Update.
coyoteTimerandjumpBufferTimer. Both should count down each frame and reset to their max value at the right moment (coyote on leaving ground, buffer on jump press). - Coyote time resets when grounded. Look for
coyoteTimer = coyoteTimeinside the grounded branch, not at the top of Update. - Jump buffer is consumed, not just checked. When the buffered jump triggers, set the timer to 0 immediately so the same press doesn't fire two jumps.
- Variable jump cut is in Update. Reading the button release belongs with input. Velocity write happens once, not in a loop.
- Ground check uses a small overlap circle, not a raycast. Raycasts miss the corners of platforms; circles don't.
How to wire it up
- Save Claude's output as
PlatformerController.cs. - Create a 2D player GameObject. Add
Rigidbody2D(Dynamic, Gravity Scale 3, Freeze Rotation Z true),BoxCollider2D. - As a child of the player, create an empty Transform called
GroundCheck. Position it at the bottom of the collider. - Attach
PlatformerController.csto the player. DragGroundCheckinto the script's groundCheck field. - Set the
groundLayermask in the inspector to whatever layer your tilemap is on. - Press Play. Walk off a ledge, then press jump 0.05s later. It should jump.
Common gotchas
The character double-jumps
Almost certainly because jumpBufferTimer isn't being zeroed when the buffered jump fires. Look for the line that triggers the jump and add jumpBufferTimer = 0; right after.
Coyote time doesn't trigger
Usually the timer gets reset every frame in Update, before it has a chance to count down. The reset should only happen when isGrounded is true, not unconditionally.
Variable jump cut feels too aggressive
The 0.5 multiplier is a starting point. Try 0.3 for a heavier feel, 0.7 for a floatier one. The whole point of SerializeField is so you can tune this in the inspector without rebuilding.
Where to go next
- Wall jump. Add a wall check (overlap on the side), set jump direction based on which side the wall is on.
- Dash. A timed velocity override on a key press. Reuse the buffer pattern for the input.
- Apex hangtime. Reduce gravity briefly when velocity.y is near zero. Adds the floaty feel of Hollow Knight.
- Convert to FSM. Once you have 4+ movement features, consider porting to the FSM structure — the same pattern works in Unity.
Use it however you want
The prompt is CC0 — paste it, modify it, ship a game with it. The output Claude gives you is yours. A link back to pixeldex.app in your project's README helps the next solo dev find this stuff.