- Home /
Smoothly rotating an object to a specific rotation.
So basically I am trying to smoothly rotate an object to match the rotation of another object. I have done some research and while I have found some things which sort of work I think they are more complex than I need. I also don't really get quaternions or eulers, so while I'll take a script that'll work, I would really appreciate if someone could explain a little bit about how the code works as well. However like I said I'll be happy with anything that works with or without explaination.
Answer by unity_ek98vnTRplGj8Q · Feb 06, 2020 at 04:20 PM
"Smooth" can mean different things, so this may not give you the exact behavior that you want, but I can help you modify the code if you want something different. I will also give you a brief explanation of quaternions and euler angles in the comments, but there is not much to explain with this code other than Quaternion.Slerp takes in a starting rotation and a target rotation and returns a rotation somewhere in the middle based on the size of the third argument, which should be somewhere between 0 and 1.
public Transform otherObject;
public float speed;
void Update(){
transform.rotation = Quaternion.Slerp(transform.rotation, otherObject.rotation, speed*Time.deltaTime);
}
When we think about an object's orientation, it's very intuitive to think about a rotation about each of the 3 axis (x, y, and z). Imagine you are standing in front of a wall looking at a painting that is slightly above and to the right of you, and you want to describe the orientation of your head while looking directly at that painting. You could say your head is rotated up 20 degrees about the x axis, since the painting is slightly above you, and furthermore your head is rotated 10 degrees to the right about the y axis, since the painting is slightly to your right. Therefore we can describe your heads orientation as a Vector3 -> (20, 10, 0)
. These 3 numbers are known as the Euler Angles, simply the amount about each axis you rotate to get a given orientation.
While Euler Angles are intuitive to use, you quickly find that you will run into some problems while using them (I won't go into detail but if you are curious you can look up gimbal lock as well as differing euler conventions). Additionally, for any given orientation you can have multiple different euler representations of it. To get around these problems, we use Quaternions, which are a more complex mathematical representation of rotations that do not suffer from any of these issues. This is really all you need to know about them. You don't need to know how they work, or what their internal values mean. All the heavy lifting is done by Unity for you, all you have to do is learn what each of the helper functions unity has does. If you ever need to know the rotation about an axis, you can always convert a rotation back into euler angles using rotation.eulerAngles
(or can convert a set of Euler angles to a quaternion representation using Quaternion.Euler()
). Some very helpful functions that unity gives you are Slerp(), AngleAxis(), and LookAt(). Also know that you can multiply quaternions (ORDER $$anonymous$$ATTERS HERE), or can multiply a quaternion by a vector to rotate the vector (ORDER ALSO $$anonymous$$ATTERS HERE).
The big mistake people make is over-using euler angles. These can not only be a crutch (really the Quaternion functions unity provides should do the trick 90% of the time), but like I mentioned before can cause you to run into issues. A big no-no in unity is perfor$$anonymous$$g a read, modify, write with euler angles. For example -
//I want to make an object rotate faster and faster around the x axis, so I'm going to read the x value every frame and make it grow
Vector3 angles = transform.rotation.eulerAngles; //Read
Vector3 newAngles = new Vector3(angles.x*1.5f, angles.y, angles.z); //$$anonymous$$odify
transform.rotation.eulerAngles = newAngles; //Write
This is the kind of code that I see often that will run you into issues. The reason this mistake is so common is it's not only the way we intuitively want to approach the problem, but stuff like this will also work most of the time, so people don't realize they are doing something wrong. Ins$$anonymous$$d, do something like this
Vector3 angles;
Start() { angles = transform.rotation.eulerAngles;)
Update{
//Notice how we don't read every frame
angles.x *= 1.5f;
tranform.rotation = Quaternion.Euler(angles);
}
This was exactly what I was looking, and I got a lot out of your explanation too. I really appreciate it, Thanks!
Your answer
Follow this Question
Related Questions
Rotate camera only in 2 directions based on player touch 1 Answer
Aligning a hovercraft to two axis of a transform 1 Answer
How to Reset Quaternion/Rotation On 3D Object After Dragging Mouse? 2 Answers
How to smoothly rotate an object on only two axes? 2 Answers
Rotate an object (gun) around another (player) to always face the mouse position. 0 Answers