- Home /
How to represent a gameobject's (x,y,z) rotation as a quaternion?
I want to lerp a camera's rotation FROM (35,0,0) TO (15,0,0) and have no idea how, because I haven't gotten to Quaternions in math yet :( I also tried
Camera.transform.rotation.x = MathF.Lerp(35,15,timeToLerp);
but it said I couldn't do that, so I need to use
Camera.transform.rotation = Quaternion.Lerp(Camera.transform.rotation,???,timeToLerp);
I appreciate the help ^^
Answer by robertbu · Oct 25, 2013 at 07:02 AM
You don't have to understand Quaternion math to use Quaternions. The class comes with many helper functions. While you can Slerp from one specific rotation to another, it is easier to Slerp from the current rotation to another specific rotation. If you first set the rotation. Here is a script:
#pragma strict
var speed = 55.0; // Degrees per second;
private var qFrom = Quaternion.Euler(35,0,0);
private var qTo = Quaternion.Euler(15,0,0);
function Start() {
transform.rotation = qFrom;
}
function Update() {
transform.rotation = Quaternion.RotateTowards(transform.rotation, qTo, speed * Time.deltaTime);
}
Here's the full code that I have for both camera changes. I ultimately want to zoom in (position) on the camera's parent gameobject, and rotate from (35,0,0) to (15,0,0) to "look down" onto the parent object
Currently, the rotation still isn't changing at all, and the position I$$anonymous$$$$anonymous$$EDIATELY becomes the end position, doesn't gradually move over time. If I ins$$anonymous$$d do timeTakesToZoom * Time.deltaTime for the local position lerp's duration, nothing happens at all
//swoop in/zoom in over 1 second to see the char
float timeTakesToZoom = 1f;
//lerp the original camera's position to the zoomed in RelativePosition
post$$anonymous$$atchCam.transform.localPosition = Vector3.Lerp(post$$anonymous$$atchCam.transform.localPosition, new Vector3(0,1f,1.2f), timeTakesToZoom);
//lerp its rotation to the final rotation
Quaternion fromThis = Quaternion.Euler(35,0,0);
Quaternion toThis = Quaternion.Euler(15,0,0);
float degreesPerSecond = (35-15) / timeTakesToZoom;
post$$anonymous$$atchCam.transform.rotation = Quaternion.RotateTowards(fromThis, toThis, degreesPerSecond * Time.deltaTime);
As mentioned, this is not a from/to use. Your code should be:
float degreesPerSecond = (35-15) / timeTakesToZoom;
post$$anonymous$$atchCam.transform.rotation = Quaternion.RotateTowards(post$$anonymous$$atchCam.transform.rotation, toThis, degreesPerSecond * Time.deltaTime);
And you need to set the initial rotation before you start executing this code:
post$$anonymous$$atchCam.transform.rotation = Quaternion.Euler(35,0,0);
You have to use the current rotation as the first parameter of the RotateTowards(). Note that you can do a FromTo kind of rotation with Quaternion.Slerp(), but then you have to create a timer so that the last parameter cycles from 0.0 to 1.0 over time.
//swoop in/zoom in over 3 seconds to see the char
float timeTakesToZoom = 3f;
//lerp the original camera's position to the zoomed in RelativePosition
post$$anonymous$$atchCam.transform.localPosition = Vector3.Lerp(post$$anonymous$$atchCam.transform.localPosition, new Vector3(0,1f,1.2f), timeTakesToZoom)
//lerp its rotation to the final rotation
post$$anonymous$$atchCam.transform.rotation = Quaternion.Euler(35,0,0);
Quaternion toThis = Quaternion.Euler(15,0,0);
float degreesPerSecond = (35-15) / timeTakesToZoom;
post$$anonymous$$atchCam.transform.rotation = Quaternion.RotateTowards(post$$anonymous$$atchCam.transform.rotation, toThis, degreesPerSecond * Time.deltaTime);
I tried making the rotation this AND tried using slerp, and neither did anything. And the localPosition lerp is still happening in one frame rather than over 3 seconds... I don't understand this :/
The problem is that the assignment of the original rotation cannot be done at every frame. It needs to be done once at the start of the rotation. Take a careful look at my example code. I set the original rotation in Start(). Then you use RotateTowards() each frame with the current rotation as the first parameter.
...still not working (I'm so sorry to keep bothering you. Really do appreciate the help)
I added this to my Update()
if(movingCamForVicDance)
{
float timeTakesToZoom = 3f;
Quaternion toThis = Quaternion.Euler(15,0,0);
float degreesPerSecond = (35-15) / timeTakesToZoom;
post$$anonymous$$atchCam.transform.rotation = Quaternion.RotateTowards(post$$anonymous$$atchCam.transform.rotation, toThis, degreesPerSecond * Time.deltaTime);
}
and changed my IEnumerator to this:
float timeTakesToZoom = 3f; //IF YOU CHANGE THIS, ALSO CHANGE IT AT THE BOTTO$$anonymous$$ OF UPDATE
post$$anonymous$$atchCam.transform.localPosition = Vector3.Lerp(post$$anonymous$$atchCam.transform.localPosition, new Vector3(0,1f,1.2f), timeTakesToZoom);
movingCamForVicDance = true;
yield return new WaitForSeconds(timeTakesToZoom);
movingCamForVicDance = false;
so that the rotateTowards is called in Update ins$$anonymous$$d of the IEnumerator, its first parameter is set to the gameobject's rotation, and the initial rotation (35) is now assigned in Start()
But STILL the position lerp just immediately puts the camera at the resulting positionr ather than panning over the duration, and the camera doesn't rotate whatsoever
Answer by Bunny83 · Oct 25, 2013 at 07:02 AM
First of all when you use Camera.transform.rotation as start value you actually don't LERP anymore. It becomes a decellerated rotation. Your Mathf example does lerp because start and end value have to be constant for a linear interpolation.
To answer your ??? question:
Quaternion.Euler(15,0,0)
This creates a rotation out of the given eulerangles. Quaternions are better to represent rotations since they avoid a Gimbal lock
If you want to lerp between two rotation you have to store them both in a variable and use those to lerp. It depends on what you want.