- Home /
Rotate object to target position
I have an object in my Unity scene which receives rotation values from another script. These rotation values are angles for rotating the object in the world space (and not around object's local axes).
The object already has an orientation in World Space (say 50deg pitch, 50 deg yaw) and we can take this current orientation to be S. When the object receives rotation values like (0,180,0), it has rotate from it's current orientation by 180 degrees around Y axis (in world space). When it receives the next rotation value (0,270,0), it has to rotate from current orientation to the orientation - S + 270(around Y axis in world space)
I tried to do Quaternion.Slerp but Slerp always takes the shortest path because of which this doesn't work correctly. Here's what my code looks like right now:
IEnumerator RotateObject(Transform thisTransform, Vector3 endDegrees, float time){
Quaternion startQuat = transform.rotation;
Quaternion endQuat = transform.rotation * Quaternion.Euler (endDegrees);
float rate = 1.0f / time;
float t = 0.0f;
while (t < 1.0) {
t += Time.deltaTime * rate;
transform.rotation = Quaternion.Slerp(startQuat, endQuat, t);
yield return 0;
}
}
I am not sure how I can interpolate the eulerAngles directly, because it is not recommended to read the eulerAngles values (should be write-only), but I'd need to read the angles to get the current orientation and add/subtract rotation values to it.
If your object is not been impacted by physics, then all you have to do is maintain your own Vector3 and assign it to the transform.eularAngles. So when you do your Vector3.Lerp() or Vector3.$$anonymous$$oveTowards(), you do it to your Vector3 variable.
Answer by robertbu · May 23, 2014 at 07:21 AM
I just read your comment on my old question. In particular, you will keep a class variable...something like myAngles:
private Vector3 myAngles;
I don't know how you have your objects setup. If they always start at (0,0,0) rotation, then you can just assign Vector3.zero; Or you can make 'myAngles' public and then initialize eulerAngles to a set value. Or usually you can get away reading eulerAngles once in Start() or Awake().
After that you will always do your Lerp() to your variable. Here is a untested rewrite of your code to give you the idea:
IEnumerator RotateObject(Transform thisTransform, Vector3 deltaDegrees, float time){
Vector3 start = myAngles;
Vector3 end = start + deltaDegrees;
float rate = 1.0f / time;
float t = 0.0f;
while (t < 1.0) {
t += Time.deltaTime * rate;
myAngles = Vector3.Lerp(start, end, t);
transform.eulerAngles = myAngles;
yield return 0;
}
}
@robertbu: The objects in the World Space have their own orientation and are not at eulerAngles(0,0,0) at the start. As you mentioned, I can read the eulerAngles once on Start()/Awake() but there's a problem I see happening in this case. The very initial orientation is say S(50,50,0);
The first rotation value that comes in is 180 degrees, so endDegrees vec3 is found by S+vec3(0,180,0); and then angles are lerp-ed to reach the target orientation.
Now, the second rotation value which is 270 comes in, and the object has to move from current orientation to S+vec3(0,270,0).
However, for lerp-ing, I need to know the current euler angles of the object which I can't read because they might not have the correct representation. How would I solve this?
$$anonymous$$eanwhile, I'll give it a shot by just having myAngles as the orientation value from which to continue for the next rotation.
You do know the current eulerAngles...or at least one representation of it. As long as nothing but this code is doing the rotation, myAngles will be a representation of the current rotation. Note in re-reading your question I'm assu$$anonymous$$g that S+vec3(0,270,0) represents a delta rotation from the existing rotation. I made a small change in my code sample. Originally I assumed it was an absolute rotation.
@robertbu : Thanks. This was super helpful! Was finally able to solve the problem. You saved the day! $$anonymous$$any thanks ^ 1000. :-)
@robertbu : I happened to come back to this problem again and facing a slight problem. The above question deals with adding a rotation value to the existing orientation of the object, but I am able to do the above only in world space.
The new scenario where I am facing the problem: The object already has an orientation in World Space (say 50deg pitch, 50 deg yaw) and we can take this current orientation to be S. When the object receives rotation values like (0,180,0), it has rotate from it's current orientation by 180 degrees around Y axis (in local space). Note that in the above question, the rotation was in world space, but this new scenario has to have rotations in local space. How do I deal with euler angles in the above answer to get the same rotation in local space (i.e. the object should be rotating around its own local Y-axis in this case)?
You should probably open this as a new question with a full explanation of the setup. If you have a world rotation of (0,50,50) and then you want to apply local rotations, consider isolating the (0,50,50) in a parent object and using Transform.localEulerAngles(). You can also play games with Quaternion.AngleAxis() using the the local axes (transform.up, transform.right, transform.forward) converted to world coordinates. And there are some other approaches.
Your answer
Follow this Question
Related Questions
Rotation direction in coroutine 2 Answers
How to smoothly rotate an object on only two axes? 2 Answers
Rotating a direction Vector3 by Quaternion 2 Answers
allows users to view 360º content without a VR headset 0 Answers
3D nested Turret Prefab Rotation 1 Answer