Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Clamped Rotate 3D Object on Y and Z axis only with OnMouseDrag()

Discussion in 'Editor & General Support' started by Vi-V-eK, May 29, 2019.

  1. Vi-V-eK

    Vi-V-eK

    Joined:
    Jun 9, 2017
    Posts:
    11
    Hello guys I've been struggling in rotating a gameobject on y and z axis only with Y value clamped between (-90 & -120) & Z value between (0 & -10). I've tried many online solutions with eulerangles and rotation and still stuck. I want to rotate 3D model with drag so I thought that OnMouseDrag would work. Any help would be really appreciated. Thanks.
     
  2. IronLionZion

    IronLionZion

    Joined:
    Dec 15, 2015
    Posts:
    78
    Could you be more specific? Are you saying that OnMouseDrag doesn't do anything? Or are you saying that you're having trouble with clamping the angles?
     
  3. Vi-V-eK

    Vi-V-eK

    Joined:
    Jun 9, 2017
    Posts:
    11
    Actually I found one solution but It also has some bugs...can you help me out

    1. Vector2 lastPosition;
    2. public float speed = 1f;
    3. private void OnMouseDrag()
    4. {
    5. //Debug.Log(transform.rotation.eulerAngles.y);
    6. if (Input.mousePosition.x < lastPosition.x + 10)
    7. {
    8. print("condition 1");
    9. transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, Mathf.Clamp(transform.rotation.eulerAngles.y + speed, 230, 270), transform.rotation.eulerAngles.z);
    10. }
    11. else if (Input.mousePosition.x > lastPosition.x - 10)
    12. {
    13. print("condition 2");
    14. transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, Mathf.Clamp(transform.rotation.eulerAngles.y - speed, 230, 270), transform.rotation.eulerAngles.z);
    15. }
    16. if (Input.mousePosition.y > lastPosition.y + 10)
    17. {
    18. print("condition 3");
    19. transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, Mathf.Clamp(transform.rotation.eulerAngles.z - speed, 340, 360));//org
    20. }
    21. else if (Input.mousePosition.y < lastPosition.y - 10)
    22. {
    23. print("condition 4");
    24. transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, Mathf.Clamp(transform.rotation.eulerAngles.z - speed, 360, 340));//org
    25. }
    26. }
    27. void OnMouseUp()
    28. {
    29. transform.rotation = Quaternion.Euler(0, 270, 360);
    30. }
     
  4. Vi-V-eK

    Vi-V-eK

    Joined:
    Jun 9, 2017
    Posts:
    11
    there is still some error in Z axis. Its quickly snaps between the values used in code but that's not the case with Y axis. The y axis is working perfectly. My 3D model is set as (0,270,360) and it is supposed to go to (0,230,340).
    Please look at the above code and help me?
     
  5. IronLionZion

    IronLionZion

    Joined:
    Dec 15, 2015
    Posts:
    78
    Clamping rotations using euler angles can be a pain in the backside, since euler angles use absolute values. Negative values and values greater than 360 wrap around to fall within the range [0 >= angle < 360]. So clamping an angle within a range of -90 and 90 for example, is not as simple as clamping between 90 and 270. You'll have to clamp between (0 to 90) or (270 to 360). But if the initial angle falls between 90 and 270, do you clamp down to 90 or up to 270? That will depend on if you're decreasing of increasing the angle. So a little more coding on you part is required.

    A possible workaround:
    There is a 'ClampRotationAroundXAxis' function in the 'MouseLook' script of the FPS controller in the Standard Assets folder. A modification of this can be used to clamp rotations around any other axis. However, this only works when the other 2 axes have zero rotation. So you set up sort of a gimball system which includes a hierarchy of transforms that represent the axes to rotate around, and then parent the object to be rotated to the last transform in the hierarchy. Rotation of the object is performed by rotating the parent transforms only around the axes that they represent.

    Here's an Example:

    clamp_rotate.PNG

    Code (CSharp):
    1. public float speed = 1f;
    2. // Assign these in the inspector
    3. public Transform yAxis, zAxis;
    4. // Used to reset the rotations
    5. Quaternion origYRot, origZRot;
    6.  
    7. private void Start()
    8. {
    9.     origYRot = yAxis.localRotation;
    10.     origZRot = zAxis.localRotation;
    11. }
    12.  
    13. private void OnMouseDrag()
    14. {    
    15.     float mouseX = Input.GetAxis("Mouse X");
    16.     float mouseY = Input.GetAxis("Mouse Y");
    17.  
    18.     // Rotate around y axis
    19.     if(mouseX < 0f)
    20.         yAxis.Rotate(0f, speed, 0f);
    21.     else if(mouseX > 0f)
    22.         yAxis.Rotate(0f, -speed, 0f);
    23.     // Rotate around z axis
    24.     if(mouseY < 0f)
    25.         zAxis.Rotate(0f, 0f, speed);
    26.     else if(mouseY > 0f)
    27.         zAxis.Rotate(0f, 0f, -speed);
    28.  
    29.     // Clamp z axis rotation
    30.     zAxis.localRotation = ClampRotation(zAxis.localRotation, -10f, 0f, 2);
    31.     // Clamp y axis rotation
    32.     yAxis.localRotation = ClampRotation(yAxis.localRotation, -120f, -90f, 1);
    33. }
    34.  
    35. void OnMouseUp()
    36. {
    37.     // Reset Rotations
    38.     yAxis.localRotation = origYRot;
    39.     zAxis.localRotation = origZRot;
    40. }
    41.  
    42. // A modification of the ClampRotationAroundXAxis function in the MouseLook script of the fps controller in Standard Assets package
    43. private Quaternion ClampRotation(Quaternion q, float min, float max, int axis /*0=x, 1=y, 2=z*/)
    44. {
    45.     q.x /= q.w;
    46.     q.y /= q.w;
    47.     q.z /= q.w;
    48.     q.w = 1.0f;
    49.  
    50.     float angle = 2.0f * Mathf.Rad2Deg * Mathf.Atan(q[axis]);
    51.     angle = Mathf.Clamp(angle, min, max);
    52.     q[axis] = Mathf.Tan(0.5f * Mathf.Deg2Rad * angle);
    53.  
    54.     return q;
    55. }
     
    Last edited: May 31, 2019