# How to clamp rotation on a specific axis?

I want to rotate an object based on mouse delta but I am unable to clamp it because I only want it to turn so far on a specific axis.

Vector2 inputAxis;
GameObject obj;
//
//
//
void Update()
{
obj.transform.rotation *= Quaternion.AngleAxis(inputAxis.y,Vector3.Right);
obj.rotation.eulerAngles = new Vector3(Mathf.Clamp(obj.rotation.eulerAngles.x,-45,45),obj.transform.rotation.y,obj.transform.rotation.z);
}


Just results in an error code "Cannot modify the return value of 'Transform.rotation' because it is not a variable." I've googled several pages on how to do this and pretty much every one of them have this almost exact type of clamping so I'm not sure what I'm missing.

I've also tried these...

Vector3 targetRotation = obj.transform.eulerAngles;
targetRotation.x = Mathf.Clamp(targetRotation.x, -45,45);
obj.transform.eulerAngles = targetRotation;


...as well as...

Vector3 targetRotation = obj.transform.eulerAngles;
targetRotation.x = Mathf.Clamp((targetRotation.x<=180)?targetRotation.x:(360-targetRotation.x), -45f, 45f);
obj.transform.eulerAngles = targetRotation;


BUT both, instead of going less than 0, will snap to back to 45 instead.

I've also tried something else...

// in order to put both units in the positive.
float targetAngle = 45;
Vector3 targetRotation = new Vector3(180f,0,0); //face the other direction
targetRotation.x *= inputAxis.y;//to rotate from player movement
target.x = Mathf.Clamp(target.x, 180-targetAngle, 180 + targetAngle ); //to get the clamp
target.x -= 180f; //to get it back in the right direction
obj.transform.eulerAngles = target; //and set

• Can you describe what this object you're rotating represents, and how it's supposed to be oriented? Because you've written your code in terms of Euler angles, and Euler angles behave extremely non-uniformly over their range, it's difficult for us to guess the intended behaviour from only seeing code that does not successfully produce that behaviour. Do any other scripts or other effects modify the orientation of this object, or could we simplify and assume this script is the only one? Commented Apr 21, 2023 at 21:07
• @DMGregory Yeah, sure. It's really just a simple script to change a rotation of something with the inputs, (it can be any input, I just chose mouse delta because I can get a vector direction that can move it in the other direction with the same variable). It's kind of just like a valve that the user needs to be able to move back and forth (like a car steering wheel) to "stay in the green" of the pressure gauge so I can't just animate it or "set it" to on since that would defeat the purpose of what it is. This is the only script on it for now until I figure this out. No other movement though. Commented Apr 21, 2023 at 23:17

It's generally not safe to use Euler angles as the input to a computation. Many different Euler angle representations map to the same resulting orientation, and the values need to wrap around somewhere, so this very easily leads to problems like the ones you've discovered.

You can avoid this by tracking your current rotation angle internally, and not reading it out of the eulerAngles getter. Something like this:

public class LimitedRotation : MonoBehaviour {

public Vector3 axis = new Vector3(1, 0, 0);

public float currentAngle = 0f;
public float maxAngle = 45f;
public float minAngle = -45f;

Quaternion _relativeTo;

void Start() {
_relativeTo = transform.localRotation;
}

public void Rotate(float delta) {
currentAngle = Mathf.Clamp(currentAngle + delta, minAngle, maxAngle);

var fromInitial = Quaternion.AngleAxis(currentAngle, axis);

transform.localRotation = _relativeTo * fromInitial;
}
}

• For others that stumble across this, I also added rotationSpeed for adaptability. currentAngle = Mathf.Clamp(currentAngle + (delta * rotationSpeed), minAngle, maxAngle); Commented Apr 22, 2023 at 1:35