0
\$\begingroup\$

My script(MouseLookController) is attached to a GameObject and I want to limit it's rotation between 90deg and -90deg.(Rotation is 40 deg in example image)
enter image description here

Problem is I can't access this value to check it. How can I access the rotation Z of this gameobject?

I've tried:

transform.localEulerAngles.z  
transform.rotation.z  
transform.eulerAngles.z

Meaning they won't return 40.695 value, where is this value currently stored?
Couldn't find it in the GameObject.

\$\endgroup\$
2
  • \$\begingroup\$ It's very unusual to manipulate a z (roll) angle in a mouse look controller. Generally we want to work with x (pitch) to look up & down, and y (yaw) to look left & right. Z twists/rolls the view. I notice your pitch is a full -90 degrees here, so its local forward vector (z+, the blue axis in Unity) is looking straight up to the sky. Is it possible your object is was imported with the wrong orientation, and you've added this pitch to try to correct it? If so, you should fix the orientation at the import step, or wrap it in a parent object that doesn't need to correcting orientation. \$\endgroup\$
    – DMGregory
    Mar 3 '20 at 12:48
  • \$\begingroup\$ As you said I have bad import orientation and I angled the parent to have a specific angle of the scene which might be causing a gimbal lock. \$\endgroup\$ Mar 4 '20 at 9:17
2
\$\begingroup\$

Manipulating individual components of a quaternion is almost never what you want to do.

The three imaginary components of the quaternion (x, y, z) describe your axis of rotation, and the real component (w) describes how much to rotate around it, subject to the constraint that the whole 4-vector has a length of 1 (so as you change the rotation angle, the axis vector grows and shrinks). So changing just one component doesn't make sense - the different parts of the quaternion have to change in concert.

Instead, you generally want to use the convenience methods of the Quaternion class to do your operations - which ends up making for much clearer and more intuitive code, as a bonus.

Quaternion ClampRoll(Quaternion orientation, float minRoll, float maxRoll) {

    // Find which direction the z+ axis of this orientation points in the world.
    Vector3 forward = orientation * Vector3.forward;

    // Form a reference orientation with no roll, looking in that direction.
    Quaternion noRoll = Quaternion.LookRotation(forward, Vector3.up);

    // Use this to isolate just the roll part of our orientation, removing everything else.
    Quaternion rollAlone = orientation * Quaternion.Inverse(noRoll);

    // Now we know we have the z angles alone, with no other confounding factors.
    // Use DeltaAngle to get it in the range -180...180
    float rollAngle = Mathf.DeltaAngle(0, orientation.eulerAngles.z);

    // Now we can clamp it into our desired range.
    float clamped = Mathf.Clamp(rollAngle, minRoll, maxRoll);

    // And fold it back into our roll-free rotation to finish the job.
    return noRoll * Quaternion.Euler(0, 0, clamped);
}

You might be able to skip the first few steps there, but myself I don't trust the way Euler angles wrap around, which can lead to unexpected behaviour. So I like to isolate just the rotation angle I care about, relative to the identity orientation, to minimize the potential for surprises in a corner case I didn't think about. ;)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.