Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Rotate odd behaviour

Discussion in 'Scripting' started by boby-bobs, Sep 2, 2015.

  1. boby-bobs

    boby-bobs

    Joined:
    Oct 18, 2013
    Posts:
    53
    I am using the most basic implementation of rotate for a directional light (well, for a transform really).

    While it does what I want, it doesn't seem to be working properly.

    My transform is set to start at 0,0,0 rotation.
    I'm using the docs example

    Code (CSharp):
    1.  
    2.         transform.Rotate(Vector3.right * Time.deltaTime);
    Not only is it rotating the X axis, but the Y and Z are also increasing at exponential rates.
    Now the worst part: once the X axis hits 90 degrees, it pauses for a brief period, and then starts going backwards from 90. The Y and Z get set to 0 and more strange stuff continues. This is really problematic because I want to base some stuff off the rotation of the X axis, and I cannot get passed 90 degrees.

    The truly worst part is, everything looks fine in the editor/game preview. The light is in fact rotating 360 degrees continually, but the editor and Debug.Log() tell me it gets to 90 and then starts going backwards. What's going on?
     
  2. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    So, it's properly rotating, and it's just the readouts on the inspector that look wrong?

    I think this is due to a misunderstanding of the way rotations are stored. The Euler angles that you see in the inspector are not the actual values; it stores a Quaternion (x,y,z, and w, none of which are in degrees or bear any direct relation to the X,Y,Z you see in the inspector), and converts that back to Euler angles to display in the inspector.

    Take a different approach; you should basically never count on the Euler angles of a rotation being compared to any particular number. You might use transform.forward and compare that vector (if transform.forward.z is negative, for example, the rotation is probably above 90 degrees). You might track your own local variable to determine how much time has passed, directly set transform.rotation.eulerAngles = new Vector3(yourVariable, 0f, 0f). Probably a few other ways if neither of those fit your needs.
     
    LeftyRighty likes this.
  3. boby-bobs

    boby-bobs

    Joined:
    Oct 18, 2013
    Posts:
    53
    I see. Rotation in Unity, in my opinion, is absurd. I can clearly rotate an object around axis X/Y/Z in the inspector. I can clearly read the value from this in a script. Yet I cannot set transform.rotation.x to what I want. I will try the eulerAngles method..
     
  4. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    This is not just Unity; Quaternions are a widely accepted standard for any modern 3D engine. They're faster, the math is more consistent and reliable, and they don't suffer from gimbal lock.
     
    Last edited: Sep 2, 2015
  5. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    until you try to work out a euler approach for getting around the problems they solve :p
     
  6. boby-bobs

    boby-bobs

    Joined:
    Oct 18, 2013
    Posts:
    53
    Regardless, I don't care what Unity does in the background. If I set the transform.rotation.x to add 1 degree each update, it should just do it - just like I can in the editor.
     
  7. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,744
    Allow me to explain why that's wrong.

    When you type in (180, 0, 0) in the Inspector, it's fairly clear what's going on. But let's say you type in 540. It's the same rotation, and when converted to a quaternion it'll be identical, yet the inspector still leaves it as 540. With Euler angles, there are an infinite number of numbers that all mean the same rotation (x, x+360, x+720, etc, for all three axes); all of these identical values are converted to the same quaternion. More to the point, it would be equally valid for the quaternion-to-Euler algorithm to turn a given Quaternion into (180,0,0), or (540,0,0), or (900,0,0), or (180,360,360).... it has to pick one.

    Similarly, when you use all three Euler numbers, there are other combinations where the same rotation is represented by multiple Euler combos. For example, (90,0,0) is identical to (90,90,90). And, given a particular Quaternion, it would be just as valid for Quat-to-Euler algorithm to spit out either (90,0,0) or (90,90,90) or (90,270,270). Again, when you type these into the inspector, the values stay the same as you typed them. However, when you give it a quaternion in script - which is what you're doing when you type in transform.Rotate - the inspector values for these would no longer be maintained, because a function that converts a given Quaternion to Euler values can only have one possible output - because it's an algorithm.

    So how does the Inspector maintain the values when you type them in? It cheats. It actually remembers the Euler values you type in (and, I believe, stores them this way in the scene file as well), and as long as the rotation isn't changed elsewhere, it knows that that particular Quaternion still means those values you typed in. But as soon as it doesn't have that context of "I actually typed these particular numbers", it has no way of possibly knowing what values would make sense to you.