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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Strange behaviour of Mathf.clamp with one axis of Transform.rotation.

Discussion in 'Scripting' started by Tomasz_Pasterski, Jul 2, 2018.

  1. Tomasz_Pasterski

    Tomasz_Pasterski

    Joined:
    Aug 12, 2014
    Posts:
    98
    I want to ask why this must be so convoluted?
    From the beggining, i want to have RTS camera with zoom + rotation on x axis (with bigger zoom camera rotate on x to show more of the horizont like in Starcraft when you zoom in). All works well without clamping the rotation, so when i zoom in using mouse scrollwhell there is a rotation on x Axis but when zoom reach the clamp for zoom on y camera stops (as i want), but when i further scroll the whell the angle on x still move, same when camera reach other border with max clamp on y. I observed the values on Transform component for X of rotation which works best for me so i think i simply clamp those values so the camera cant past them when zooming but NO, when i do clamp for rotation x (as presented in code) and hit "Play" camera start with 0 on x of rotation, when i comment it out all works fine except this infinite rotation on x when i keep scrolling the mouse and which i want to clamp to prevent this infinite rotation.
    Why i ask? Was thinking this simply clamp values and keep them from crossing out from values i described as max and min, those are floats and i specified for this clamp to work on value x of rotatation (rotX).
    Simply want the value x of rotation visible in inspector to move between 138 and 168, nothing more.


    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class CameraController : MonoBehaviour
    4. {
    5.  
    6.     public float panSpeed = 20f;
    7.     public float panBorderThickness = 10f;
    8.     public Vector2 panLimit;
    9.     public float scrollSpeed = 20f;
    10.     public float minY = 20f;
    11.     public float maxY = 120f;
    12.     public float dragSpeed = 2;
    13.  
    14.     void Update ()
    15.     {
    16.         Vector3 pos = transform.position;
    17.         Quaternion rot = transform.rotation;
    18.  
    19.         if (Input.GetKey ("w") || Input.mousePosition.y >= Screen.height - panBorderThickness)
    20.         {
    21.             pos.z += panSpeed * Time.deltaTime;
    22.         }
    23.         if (Input.GetKey ("s") || Input.mousePosition.y <= panBorderThickness)
    24.         {
    25.             pos.z -= panSpeed * Time.deltaTime;
    26.         }
    27.         if (Input.GetKey ("a") || Input.mousePosition.x <= panBorderThickness)
    28.         {
    29.             pos.x -= panSpeed * Time.deltaTime;
    30.         }
    31.         if (Input.GetKey ("d") || Input.mousePosition.x >= Screen.width - panBorderThickness)
    32.         {
    33.             pos.x += panSpeed * Time.deltaTime;
    34.         }
    35.  
    36.         float scroll = Input.GetAxis ("Mouse ScrollWheel");
    37.         pos.y -= scroll * scrollSpeed * 100f * Time.deltaTime;
    38.         rot.x += scroll * scrollSpeed * Time.deltaTime;
    39.  
    40.         pos.x = Mathf.Clamp (pos.x, -235, 25);
    41.         pos.y = Mathf.Clamp (pos.y, minY, maxY);
    42.         pos.z = Mathf.Clamp (pos.z, -300, -30);
    43.         rot.x = Mathf.Clamp (rot.x, 138, 168);
    44.  
    45.         transform.position = pos;
    46.         transform.rotation = rot;
    47.  
    48.         if (Input.GetMouseButton(2))
    49.         {
    50.             Camera.main.transform.position -= new Vector3(Input.GetAxis("Mouse X") * dragSpeed, 0, Input.GetAxis("Mouse Y") * dragSpeed);
    51.         }
    52.     }
    53. }
     
    Last edited: Jul 2, 2018
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,399
    Transform.rotation is a 4D quaternion; the values you're using are not remotely what you think they are. It's nothing to do with degrees and the values in the inspector are not Transform.rotation (unless you switch to debug mode).

    --Eric
     
    Tomasz_Pasterski and lordofduct like this.
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,378
    What Eric5h5 said.

    Pitch/Yaw/Roll values can be found in the 'eulerAngles' property:
    https://docs.unity3d.com/ScriptReference/Transform-eulerAngles.html

    Note though... clamping those values the way you intend are still going to act weird just due to the nature of 3-dimensional rotations. There's more than 1 rotation value that can represent the same orientation, and you don't necessarily know which range that value is going to be in when it gets returned. So you can easily get out of any clamp because eulerAngles returns an alternative version of the rotational value.
     
  4. Tomasz_Pasterski

    Tomasz_Pasterski

    Joined:
    Aug 12, 2014
    Posts:
    98
    You are the MAN, i forgot about Debug Mode and you reminded me this :D
    In normal mode i set the angle to 138 at the lowest clamped zoom i have on Y, switched to Debug mode and copy it, same with upper clamp and end up with:
    Code (CSharp):
    1. rot.x = Mathf.Clamp (rot.x, -0.358f, -0.103f);
    And thats work like a charm, exactly what i wanted, THANKS A LOT.

    Praise the Debug MODE.
    Problem solved!