Quick Question About Limiting a Rotation.

Hey guys! I’m not the best person when it comes to rotations, sorry. I have a problem. I have a flashlight attached to my first person controller. This flashlight is not static, it follows the mouse. I want to limit the rotation of the flashlight so that it doesn’t go too far off the screen. Here is the code to make the flashlight follow the mouse:

Vector3 v3Pos = Input.mousePosition;
       		v3Pos.z = moveArea;
      		v3Pos = Camera.main.ScreenToWorldPoint(v3Pos);
       		transform.LookAt(v3Pos);

And here is the code for my flashlight script:

Mathf.Clamp(transform.rotation.x, -20f , 20f);
Mathf.Clamp(transform.rotation.y, -30f , 30f);

The code to limit the rotation does not work. Please fix it and thanks a lot! :slight_smile:

“transform.rotation” as you used above is a Quaternion. A Quaternion is a 4D construct, and generally you don’t address the individual properties such as x,y,z and w. From the script reference:

[Quaternions] are based on complex numbers and are not easy to understand intuitively. Thus you almost never access or modify individual Quaternion components (x,y,z,w);

You can get euler angles from a rotation, and as a shorthand, directly from the Transform. For example, you can read:

Vector3 v3Pos = transform.euler;  

But are are issues with euler angles as well. First, for any physical rotation there are multiple euler rotations. So an object was spun around on the x axis by 180 degrees, you would expect a euler angle of (180,0,0), but the euler angle read back from the Transform might be instead (0,180,180) which represents the same rotation.

Second, you should not set individual components of a euler angle. You need to set all the as the same time by assigning a Vector3. From the script reference:

Do not set one of the eulerAngles axis separately (eg. eulerAngles.x = 10; ) since this will lead to drift and undesired rotations. When setting them to a new value set them all at once.

So limiting rotation is not a simple thing. There are complex scripts written to normalize and clamp rotations, but there are also other ways of looking at some problems that make a solution easy.

One idea for your situation you might only set the position if the mouse is within a certain area of the screen. The following code (untested) limits the LookAt to a radius of 1/2 of the screen height. You can adjust the radius by adjusting the calculation for “max_pixel_radius”.

using UnityEngine;
using System.Collections;

public class Bug16 : MonoBehaviour {
	
	float max_pixel_radius = Screen.height / 4.0f;  
	Vector2 v2Center = new Vector2(Screen.width / 2.0f, Screen.height / 2.0f);

	void Update () {
		float fT = ((Vector2)Input.mousePosition - v2Center).magnitude;
		if (fT <= max_pixel_radius) {
			Vector3 v3Pos = Input.mousePosition;
			v3Pos.z = moveArea;
			v3Pos = Camera.main.ScreenToWorldPoint(v3Pos);
			transform.LookAt(v3Pos);
		}
	}
}