Camera Relative Free Orbit

This was originally illustrated by superlol but it’s still unanswered, as far as I can tell. I’ve tried and failed.

Take the MouseOrbit script and consider the following:

Unity’s Traditional

var rotation = Quaternion.Euler(y, x, 0);


var rotation = Quaternion.AngleAxis(x, Vector3.up);
rotation *= Quaternion.AngleAxis(y, Vector3.right);

front rotate
top spin instead of rotate

I thought by changing the second way I could get the following result, but that’s where I was wrong:

Free Orbit Relative to Camera

// formula yet to be made

front rotate
top rotate

Can you bring us the formula? Does it even exist?

To achieve the behavior that you want, instead of doing this:

x += Input.GetAxis("Mouse X") * xSpeed * distance* 0.02;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02;

var rotation = Quaternion.Euler(y, x, 0);

You should do this:

x = Input.GetAxis("Mouse X") * xSpeed * distance* 0.02;
y = -Input.GetAxis("Mouse Y") * ySpeed * 0.02;

var rotation *= Quaternion.Euler(y, x, 0);

This way, the rotation will be applied directly on quaternion, instead of applying it on euler angles.

My solution to this problem was to use a carefully set-out hierarchy of transforms, each controlling a different part of the camera.

In the middle, there is the ‘target’ transform. It follows the location of the object to be orbited, but does not follow rotation (since it controls the rotation of the camera).

On the outside, where the actual camera is, is the ‘zoom’ transform. This is a child of the ‘target’ transform, and should only move its localPosition (to move towards and away from the centre).

If you like, you can put the camera itself on a third transform (for applying extra effects like screen shaking, etc) but for the purposes of the orbit-cam it is not required.

To rotate the camera, use Transform.rotate (not rotateAround, just rotate) in Space.Local by whatever x and y amounts you need, and the outside camera will move around correctly because of transform parenting!

… I assume you don’t need a code sample here?

DISCLAIMER- this is something I made a while back, and I may have forgotten how parts of it worked. If it doesn’t quite work out for you, tell me, and I’ll try to help fix it.