Players never write “the dead zone is too small” in a review. They write “the controls feel bad”, and then they uninstall. Nearly every on-screen joystick I’ve had to fix came down to the same three numbers, and none of them can be judged with a mouse in the Editor.
The dead zone: ignore the thumb’s wobble
A resting thumb is never perfectly still. Without a dead zone the character creeps around on its own. The usual fix — treat any input below 20% as zero — creates a new problem: the moment the thumb crosses the line, output jumps from 0 straight to 0.2, and fine movement becomes impossible.
Remap the rest of the range instead, so output starts from zero at the edge of the dead zone:
static Vector2 ApplyDeadZone(Vector2 input, float deadZone)
{
float magnitude = input.magnitude;
if (magnitude <= deadZone) return Vector2.zero;
// 0 at the dead zone's edge, 1 at the rim: no jump, full range.
float scaled = Mathf.InverseLerp(deadZone, 1f, Mathf.Min(magnitude, 1f));
return input / magnitude * scaled;
}It’s radial, too: checking x and y separately creates a square dead zone that makes diagonals feel sticky. Somewhere between 0.1 and 0.15 of the radius is a good place to start.
Travel: measure it in millimetres, not pixels
How far the thumb must move to reach full speed is a physical distance. Size it in pixels and it feels twitchy on a small phone and sluggish on a tablet. Screen.dpi converts, with a fallback for the devices that report zero:
// About 11 mm of travel, whatever the screen.
float radius = Screen.dpi > 0 ? 0.45f * Screen.dpi : Screen.height * 0.12f;The centre: fixed, floating or dynamic
A fixed stick sits in one place, so the thumb has to find it without looking. A floating stick puts its centre wherever the thumb first lands, which most players prefer in action games. A dynamic stick goes one step further and drags its centre along when the thumb travels past the rim, so reversing direction is instant instead of a long slide back:
Vector2 delta = touch - center;
if (delta.magnitude > radius) center = touch - delta.normalized * radius;
Vector2 input = (touch - center) / radius;Test with a thumb, not a mouse
A mouse is precise and a thumb isn’t. The Device Simulator is fine for layout, but tune the feel on a real phone, in both hands, on the smallest and the largest screen you support. Watch someone else play without telling them anything: if they keep re-planting their thumb, the stick is too small or fixed in the wrong place.