Mapping Square Input to Circle in Unity 2017

Moving the player using the input from a keyboard of joystick is easy, though as soon as you start moving in a diagonal direction either using thumb sticks or pressing down two keys at once, you may notice the player will move faster compared to walking forward of sideways.

The reason is the input axis combined results in a longer vector, which can be calculated using simple pythagoras, which shows the combined speed is 1.4142 times faster.

var a = new Vector2(0, 1);
var b = new Vector2(1, 0);
var c = a + b; // Vector2(1, 1)

// pythagoras says length of c = sqrt(a^2 + b^2)
// c = sqrt(1 + 1) = sqrt(2) = 1.4142...
var cMagnitude = Mathf.Sqrt(a.magnitude * a.magnitude + b.magnitude * b.magnitude);

I’ve seem many people suggest to simply normalize the input, which works perfectly if you don’t care about the sensivity. However, using thumb sticks should in my opinion allow the player to move fast and slow.

 

Based on the formula found at http://mathproofs.blogspot.com/2005/07/mapping-square-to-circle.html, we can remap the square input to a circular one like so:

// get input
var input = new Vector2(
	Input.GetAxisRaw("Horizontal"),
	Input.GetAxisRaw("Vertical")
);

// map square input to circle, to maintain uniform speed in all directions
var inputCircle = new Vector2(
	input.x * Mathf.Sqrt(1 - input.y * input.y * 0.5f),
	input.y * Mathf.Sqrt(1 - input.x * input.x * 0.5f)
);

 

Philip Nowell also created a nice illustration of what’s happening.

 

It is worth mentioning that the Xbox Controller does not seem to output a perfect square. More like a rounded square as discussed on the Unreal forums: https://answers.unrealengine.com/questions/226365/analog-stick-input-traces-a-square.html