| Engine | Unity 2022.3 LTS or newer |
|---|---|
| Language | C# |
| Time to run | ~2 minutes |
| Level | Beginner — comfortable opening Unity |
| Output | One file, ~80 lines |
| Dependencies | None. No packages, no plugins. |
The prompt
Open a fresh chat at claude.ai/new, paste this in as your first message, and hit send. Don't add anything else.
$ Build me a top-down 2D player controller for Unity 2022.3+ // constraints - Single C# MonoBehaviour, no external packages. - WASD movement. Normalize the input vector so diagonals don't sprint. - Speed is a [SerializeField] float, default 5. - Sprite-renderer flip on horizontal input, only when input != 0. - Animator parameters: speedX (float), speedY (float), isMoving (bool). - Input buffer of 0.05s so dashes feel responsive if pressed a frame too early. - Snap-to-pixel option, toggleable via [SerializeField] bool, default off. // physics - Use Rigidbody2D for movement, MovePosition in FixedUpdate. - Read input in Update. Don't write physics from Update. // return format - One file. No prose before or after the code. - Comments only where the constraint is non-obvious. - File should be named PlayerController.cs.
What this gets you
A working top-down character that moves predictably in eight directions. Nothing fancy — but the kind of "feel" details that usually get cut from beginner tutorials are baked in: normalized diagonals so you can't speed-cheese, an input buffer so a dash press near the edge of a frame still triggers, and proper Update-vs-FixedUpdate separation so the character doesn't stutter at low frame rates.
It's the controller you'd actually keep in a real project, not a stripped-down demo you have to rewrite the moment you add real gameplay.
What good output looks like
If Claude got this right, the script should pass these checks. Read the output before you paste it into Unity.
- One file, no companion classes. If Claude split it into a State, Input, and Movement class, ask it to consolidate. The point is a drop-in starter.
- FixedUpdate moves the Rigidbody2D, Update reads input. If physics is being written in Update, ask Claude to fix it before you paste.
- Diagonal movement is normalized. Look for
.normalizedor an explicit length check on the input vector. - The input buffer actually buffers. Look for a small float field (e.g.
bufferTimeorlastInputAt) that gates dash availability. - Animator parameters are set every frame, not in conditionals. If
speedXonly updates when input != 0, dropping input won't blend cleanly back to idle. - No magic numbers. Speed, buffer time, and snap toggle should all be SerializeField, so you can tune them without recompiling.
How to wire it up
- Save Claude's output as
PlayerController.csin yourAssets/folder. - Create a 2D GameObject for your player. Add a
Rigidbody2D(set Gravity Scale to 0 for top-down) and aBoxCollider2D. - Add an
Animatorcomponent. Either drop in your existing controller or right-click → Create → Animator Controller and add float parametersspeedX,speedY, plus a boolisMoving. - Attach
PlayerController.csto the GameObject. - Press Play. WASD should move you smoothly. The sprite should flip when you press A or D.
Common gotchas
The character jitters when moving
Almost always a Rigidbody2D Interpolation issue. Set Interpolation to Interpolate on the Rigidbody2D component. If you also have Cinemachine following the player, set the Cinemachine Brake Update Method to FixedUpdate so they tick on the same clock.
The animator doesn't transition to idle
You probably have an empty Animator Controller. Claude assumes you've at least set up the parameters. Add an Idle and a Walk state, set the transitions, and make sure your transitions read the isMoving bool — not the speed floats.
The pixel-snap option looks blurry
Pixel snap only works if your camera is sized to your pixels-per-unit. Set Camera Pixel Perfect to true (or use the Pixel Perfect Camera component from URP). If you're not doing pixel art, leave the snap toggle off.
Where to go next
This is intentionally minimal. When you're ready to extend it, here's the order I'd add things:
- Dash. Modify the input buffer field, add a velocity burst on space-bar.
- Sprint hold. Multiplier on speed while shift is held. Two lines of code.
- Knockback. A coroutine that overrides movement input for N frames after a hit.
- State machine. Once you have 3+ states (idle, walk, dash, hurt) it's worth promoting to an FSM. See the FSM-based controller prompt for a clean structure you can port back to Unity.
Why this prompt is shaped this way
Three things make this prompt work better than "write me a Unity player controller":
- Constraints, not requests. Telling Claude what the output cannot do (no packages, no companion classes) is more reliable than asking nicely for what you want.
- Return format up top. "One file. No prose before or after the code." cuts out the explanation Claude would otherwise write, which clutters the paste.
- Specify the version. Unity APIs change. Pinning
2022.3means Claude won't suggest something deprecated, and won't reach for the new Input System unless you ask.
Use it however you want
The prompt itself is CC0 — paste it, modify it, sell something built with it. No attribution required. Same for the output Claude gives you. If you're feeling generous, a link back to pixeldex.app in your project's README helps the next solo dev find this stuff.