Posted by: Morten Nobel-Jørgensen | October 22, 2010

## Spherical coordinates in Unity What is spherical coordinates and where are they useful? These are some of the questions I’ll answer in this blog that also contains a implementation of spherical coordinates for the Unity Game game engine.

The cartesian coordinate system The cartesian coordinate system in 3D

First take a step back and look at how positions usually are specified in 3D space. Positions in space are usually written in the cartesian coordinate system, where the 3 axis X, Y, and Z span the space. A point in the cartesian coordinate system can be defined using a vector (x,y,z) from the origin to the point, where x is is the distance traveled along the x axis, y is the distance traveled along the y axis and z along the z axis. The cartesian coordinate works well as the reference coordinate system. Along with the cartesian coordinate system comes a lot of useful math using vectors and matrices.
Note that I have chosen to let the y axis point upwards as it does in Unity.

The spherical coordinate system

Spherical coordinate system is an alternative coordinate system, where two orthogonale coordinate axis define the world space in 3D. The zenith axis points upwards and the azimuth axis points to the side. To define a point in this system the following is needed:

• Radius: the distance from the origin to the point
• Elevation angle: the angle between the plane (with zenith axis as normal) and the line from the origin to the point
• Polar angle: the rotation around the zenith axis

Elevation angle and polar angles are basically the same as latitude and longitude.
Note that a point specified in spherical coordinates may not be unique.
The spherical coordinate system I’ll be looking at, is the one where the zenith axis equals the Y axis and the azimuth axis equals the X axis.

Converting between spherical and cartesian coordinates

To convert from spherical coordinates to cartesian coordinates can be done the following way in c#:

```public static void SphericalToCartesian(float radius, float polar, float elevation, out Vector3 outCart){
float a = radius * Mathf.Cos(elevation);
outCart.x = a * Mathf.Cos(polar);
outCart.z = a * Mathf.Sin(polar);
}
```

And converting from cartesian coordinates to spherical coordinates:

```public static void CartesianToSpherical(Vector3 cartCoords, out float outRadius, out float outPolar, out float outElevation){
if (cartCoords.x == 0)
cartCoords.x = Mathf.Epsilon;
+ (cartCoords.y * cartCoords.y)
+ (cartCoords.z * cartCoords.z));
outPolar = Mathf.Atan(cartCoords.z / cartCoords.x);
if (cartCoords.x < 0)
outPolar += Mathf.PI;
}
```

A full general purpose implementation of spherical coordinates can be found as a part of my camera library for Unity:
http://github.com/mortennobel/…/SphericalCoordinates.cs

Usages of spherical coordinates

One usage of spherical coordinates is in third person chase camera systems, where the player controls both the player-character and the movement of the camera. On console games this is usually done by mapping one joystick to control player movement and another to control camera movement. The camera movement is restricted to move around the player giving – a perfect example of how to use spherical coordinates. The radius is simple the distance between the player character and the camera, the elevation angle can be mapped to the vertical joystick state and the polar angle can be mapped to the horizontal joystick state.

A complete implementation of a chase camera using spherical coordinates can be found as a part of my camera library:

http://github.com/mortennobel/CameraLib4U/

## Responses

1. your blog is great! thanx for sharing these knowledge.

2. I tested your shperical to cartasian convertion function and I got incorrect values, this is what I tested:

SphericalToCartesian(20, 0, 14)

if polar parameter is 0 then x must be 0 because you are not rotating on the z axis (simple logic) and this is what returns:

x = 2.734744364156672
y = 19.812147113897407
z = 19.812147113897407

3. Thanks for the great info,

You may want to use ATan2 instead of ATan. It takes two arguments instead of one so that it can return the angle in the correct quadrant and handles cartCoords.x being zero. This avoids the need to set cartCoords.x to epsilon. and the need to adjust the returned angle.

4. 