So, I’m sure this has to do with my utter ignorance of the Quaternion/Euler paradigm, but…
I need to be able to use the keyboard to rotate an object very accurately around the objects’ X,Y, and Z axis (separately).
I’m using the following script:
var rotationSpeed : float = 10;
private var minimumY = -360;
private var maximumY = 360;
private var rotationY : float;
private var minimumX = -360;
private var maximumX = 360;
private var rotationX : float;
private var minimumZ = -360;
private var maximumZ = 360;
private var rotationZ : float;
function Update () {
rotationX += Input.GetAxis("RotateX") * rotationSpeed;
rotationX = ClampAngle(rotationX, minimumX, maximumX);
rotationY += Input.GetAxis("RotateY") * rotationSpeed;
rotationY = ClampAngle(rotationY, minimumY, maximumY);
rotationZ += Input.GetAxis("RotateZ") * rotationSpeed;
rotationZ = ClampAngle(rotationZ, minimumZ, maximumZ);
transform.rotation = Quaternion.AngleAxis(rotationY, Vector3.up);
transform.rotation *= Quaternion.AngleAxis (rotationX, Vector3.right);
transform.rotation *= Quaternion.AngleAxis (rotationZ, Vector3.forward);
}
static function ClampAngle (angle : float, min : float, max : float) {
if (angle < -360)
angle += 360;
if (angle > 360)
angle -= 360;
return Mathf.Clamp (angle, min, max);
}
When launched, it rotates fine at first around the X and Y axes. But, then, after you’ve rotated a bit - and rotated around other axes, when you try to rotate around X or Y, it rotates around some strange axis (not the objects). For some reason rotating around the Z axis always works.
You can see how this works by creating a cube in a scene and dropping this script on it.
Transform.TransformDirection() converts a local axis to a world axis, and since transform rotations are relative to the world, you have to use that function to say, “I want to rotate this much around my object’s ‘up’ axis, so translate that axis into the correct world axis.”
I’m not sure if Maker16’s code will give you exactly the behavior you’re looking for. (Maybe it will - if it does, you can ignore this post
If you want all rotations to occur about the corresponding local axes at all times, you’ll need to do something like the following:
function Update()
{
Quaternion rotX = Quaternion.AngleAxis(
Input.GetAxis("RotateX") * rotationSpeed, Vector3.right);
Quaternion rotY = Quaternion.AngleAxis(
Input.GetAxis("RotateY") * rotationSpeed, Vector3.up);
Quaternion rotZ = Quaternion.AngleAxis(
Input.GetAxis("RotateZ") * rotationSpeed, Vector3.forward);
// I'm pretty sure Unity uses standard quaternion multiplication order,
// but if this gives you the wrong results, try reversing the order of
// multiplication:
transform.rotation = transform.rotation * rotX;
transform.rotation = transform.rotation * rotY;
transform.rotation = transform.rotation * rotZ;
// I'm not sure if Unity has a 'normalize' function for quaternions. If
// it doesn't though, you can write one yourself:
transform.rotation = QuaternionNormalize(transform.rotation);
}
Turns out, I got it to work with this (probably inefficient) script:
var leftCamera : GameObject;
var rightCamera : GameObject;
function Update() {
//Right Camera Controls
if (Input.GetKey("o")){
rightCamera.transform.Rotate(Vector3.right, Time.deltaTime*10);
}
if (Input.GetKey("p")){
rightCamera.transform.Rotate(-Vector3.right, Time.deltaTime*10);
}
if (Input.GetKey("l")){
rightCamera.transform.Rotate(Vector3.up, Time.deltaTime*10);
}
if (Input.GetKey(";")){
rightCamera.transform.Rotate(-Vector3.up, Time.deltaTime*10);
}
if (Input.GetKey(".")){
rightCamera.transform.Rotate(Vector3.forward, Time.deltaTime*10);
}
if (Input.GetKey("/")){
rightCamera.transform.Rotate(-Vector3.forward, Time.deltaTime*10);
}
//Left Camera Controls
if (Input.GetKey("u")){
leftCamera.transform.Rotate(Vector3.right, Time.deltaTime*10);
}
if (Input.GetKey("i")){
leftCamera.transform.Rotate(-Vector3.right, Time.deltaTime*10);
}
if (Input.GetKey("j")){
leftCamera.transform.Rotate(Vector3.up, Time.deltaTime*10);
}
if (Input.GetKey("k")){
leftCamera.transform.Rotate(-Vector3.up, Time.deltaTime*10);
}
if (Input.GetKey("m")){
leftCamera.transform.Rotate(Vector3.forward, Time.deltaTime*10);
}
if (Input.GetKey(",")){
leftCamera.transform.Rotate(-Vector3.forward, Time.deltaTime*10);
}
}