- Home /
Rotation Values Garbled When Set By Code
I'm trying to set a simple object's rotation to 90 degrees in, say, the z axis from code, and getting really weird imprecision when trying both:
obj.transform.eulerAngles=new Vector3(0,0,90);
and also:
obj.transform.Rotate(0,0,90);
In either case, I print the value of eulerAngles.z immediately afterward, and it reports it as 90.00001, though the Inspector reports 90.00002 or 90.00003 in about 80% of cases, and once in a while it's some random value in the 70s or 80s range, sometimes even knocking the other 2 axes by a few degrees.
So it's initially off by at least 0.0001 when set, which is already weird, and then something else must be mangling it afterward to totally-off values. I've checked the rest of my code and nothing else messes with its rotation. Setting the value to 90 manually in the inspector raises no such problem, so I don't know what I'm missing with the code.
P.S. This is a little deja-vu; I recall having this problem a long time ago but not the solution...
Answer by blitzen · Feb 16, 2012 at 05:23 PM
It seems to be indeed the "Interpolation" setting of the object's rigidbody. When I set it to "None", the odd behaviour goes away, making it now a solid 0 or 90.00001. I guess if you have an object with interpolated physics and want to set its rotation, you'll have to make sure its interpolation is temporarily off:
RigidbodyInterpolation interp=obj.rigidbody.interpolation;
obj.rigidbody.interpolation=RigidbodyInterpolation.None;
obj.transform.eulerAngles=new Vector3(0,0,90);
obj.rigidbody.interpolation=interp;
Meanwhile, yes thanks Syclamoth the tiny 0.00001 differences are likely from floating point error. My point of curiosity on that regard is, when you set its rotation values in the inspector, you're still setting eulerAngles which will then need to be converted to Quaternions just the same. Funny how it doesn't show the small floating-point error then.
Answer by syclamoth · Feb 16, 2012 at 06:15 AM
Have you heard of a little thing called 'Floating Point Error'?
Long story short, those values are stored in scientific notation. That is to say, 90 will be stored as '9 10 ^ 1' and 0.00003 will be stored as '3 10 ^ -5'. Of course, they are a little more precise than that, but the practical upshot of this is that if you are attempting to resolve digits that are a long way away from the most significant one, you will encounter inaccuracies.
In your case, it's really nothing to worry about. You can't expect float-based quaternions to be exactly perfect, and the differences between what you see there and the desired 'real' value are too small to measure anyway (by definition). The reason why the 3-axis values turn out strangely sometimes, is because of the two-way nature of the calculation.
When you use 'transform.Rotate' (or, for that matter, eulerAngles), it converts the 3-axis value into a Quaternion, which stores the actual rotation. However, when you look at the inspector, it retrives this quaternion, and renders it back out into euler-angle notation! As you can see, there are small inaccuracies in both of these processes. So, when you set the values manually, because that is the initial source of the value, they will naturally be correct!
So, there isn't a solution, exactly, but neither is it exactly a problem.
if(GUI.Button(new Rect(10,100,128,16),"Rotate Z")){
obj.transform.eulerAngles=new Vector3(
obj.transform.eulerAngles.x,
obj.transform.eulerAngles.y,
obj.transform.eulerAngles.z==0?90:0);
}
Value of localRotation.z in inspector when hitting repeatedly:
90.00003
0
90.00001
0
90.00002
0
75.57398
0
82.93819
0
90.00002
9.954305
And the object is visibly tilted off. That strikes me as exactly a problem.
I tried it on a brand-new cube, and it didn't have the sporadic nowhere-near-90-or-0 values that were shown above. The only thing my erratic objects do have that the new cube doesn't is a rigidbody with the following values:
$$anonymous$$ass: 1
Drag: 1
Angular Drag: 1
Use Gravity: Off
Is $$anonymous$$inematic: On
Interpolate: Interpolate
Collision Detection: Discrete
Upon removing it, the erratic values seem to have stopped. I thought $$anonymous$$inematic meant no physics applied; does something in the above rigidbody mess with manual changes in rotation?
I think this is a different problem. From your question, I assumed that you were only getting 0.0001 or so errors, but this seems more severe. $$anonymous$$eep in $$anonymous$$d that manipulating rigidbodies outside of FixedUpdate (even if they're kinematic) can cause unexpected results- see if you can defer the calculation until the next fixedUpdate (by setting a flag or something) and see what happens.