- Home /
Weird rotation with Transform.eulerAngle
Hey guyz,
I want a sun go around my level and this is gonna be done with a constant incrementing of it's rotation.x using the Transform.Rotate function.
But I want to set the time at any moment ingame and the sun's rotation has to change, too For those who don't understand me: at 0am rotation shall be 270° so the sun shines from down to up and no light is on the terrain. At 12am the rotation shall be 90°, becouse then the sun shines from above and lights everything.
I tried this: sun.eulerAngle = new Vector3(360 * currentTime / maxTime, 0, 0);
but at ~90° the sun acts completely weird!! it flips from the negative of it's current x-rotation to the positive, BUT: this bug only appears for the x-axis >_<
what am i doing wrong?
Have you tried setting it directly to see what happens? $$anonymous$$g.
sun.eulerAngle = new Vector3(89.9);
sun.eulerAngle = new Vector3(90.1);
Best to simplify as much as possible. If that's acting weird, let me know, and I'll set up a blank project and see if I can reproduce your issue.
Answer by Kryptos · Jan 09, 2012 at 11:53 PM
you just encounter what is called a gimbal lock, when one axis coincides with another one (http://en.wikipedia.org/wiki/Gimbal_lock).
To avoid such a case, you should use quaternions (http://unity3d.com/support/documentation/ScriptReference/Quaternion.html)
This can be done transparently by creating quaternion using Quaternion.LookRotation() or directly changing a gameObject's rotation with transform.LookAt().
Well, Unity always uses quaterions to represent a rotation. That's actually where this problem comes from. It's the conversion between a quaternion and eulerangles. Reading back the eulerangles after assigning a gimbal-lock combination will result in eulerangles which represents the same rotation, but with different values. That's why the documentation says you shouldn't increment(read / change / write) the eulerangles.
It's better to set them to absolute values that don't rely on the previous ones. Usually you would use localEulerAngles which is equal to eulerAngles for GameObjects without a parent. Childobjects are affected in localspace so you can use a parent to setup the rotation axis and use the childs localRotation / localEulerAngles to rotate the child.
I think LookAt or LookRotation are the most inappropriate functions for this task. AngleAxis will create a rotation around a specific axis but if the rotation should be around a local axis (x,y or z) it's easier to just use Quaternion.Euler or like already mentioned eulerAngles / localEulerAngles which uses Quaternion.Euler internally.
Answer by kack93 · Jan 09, 2012 at 11:14 PM
facepalm
The point is that i CANNOT do this (what I actually did)
sun.eulerAngle = new Vector3(360 * (currentTime / maxTime), sun.eulerAngle.y, sun.eulerAngle.z);
BUT
sun.eulerAngle = new Vector3(360 * (currentTime / maxTime), 0, 0);
which I cannot understand, but anyways I got it now...
That's because your rotation is absolute and you only change x. This won't work in cases where y and z aren't "hardcoded"