I'm making a little game where you control a bunker on the ground defending itself from bombers and paratroopers. The bunker has a cannon which the player can rotate to aim at her enemies. My problem is that there is no limit to the rotation, so right now the player can aim the cannon straight down into the ground. What I would like to do is to limit the possible rotation between the values of, say, 0 to 180 along the x-axis.
So how can I limit the rotation values for an object?
Hi @joel_b , I had a related issue and came across this post while searching. Just wanted to say thanks for taking the time to write this, I've had an issue with Quaternions in the MouseLook script for a long time, but never altered they way I handled rotations until reading your transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, -rotationZ); line. After that I was able to make my force-player-look code work just fine without weird interactions with the Quaternion. So thanks for spurring on my thinking!
There is a slight improvement that can be made to this. Instead of separating rotationZ into it's own variable, and then repeating tranform.localEulerAngles._, you can use the fact that Vector_ are structs, and passed-by-value. Just manipulate the final localEulerAngles vector directly and then plug it back to the transform: var rotation = transform.localEulerAngles; rotation.z = Mathf.Clamp (rotation.z + Input.GetAxis("Mouse X") * sensitivityZ, -90, 90); transform.localEulerAngles = rotation;
You can limit the rotation of an object like this, for example if you wanted to limit the X-rotation of an object between 30 and 150 degrees:
float MinClamp = 30;
float MaxClamp = 150;
// Other movement needs to be calculated first, so
// we use LateUpdate() instead of Update().
void LateUpdate()
{
transform.rotation.eulerAngles = new Vector3(
Mathf.Clamp(transform.rotation.eulerAngles.x, MinClamp, MaxClamp),
transform.rotation.eulerAngles.y,
transform.rotation.eulerAngles.z
);
}
You can obviously modify this to clamp any angle and any value you want, and it can be in its own script file, you don't have to include it in another script.
Limiting a single axis using eulerAngles tends to be quite problematic due to internal quaternion conversions. For example, this code will fail when you try to rotate X past 90. It won't work for values like min=-30, max=30 either. It's generally better to track rotations yourself, like the MouseLook script does. (Just to nitpick, transform.rotation.eulerAngles is redundant; you only need transform.eulerAngles.)
@SpikeX: Yes, use your own variable for tracking the rotation in combination with a ClampAngle function, and apply that to the transform, like MouseLook does. :)
@Eric5h5 I think you can get the negatives to work with a little bit of logic. Like: var localEuler = transform.localEulerAngles; if (localEuler.z > 180) localEuler.z = -360 + localEuler.z; localEuler.z = Mathf.Clamp(localEuler.z, min, max); transform.localEulerAngles = localEuler; As a (way) more experienced programmer, are there any pitfalls you can see with something like that?
This limits how far from vertical the Y-axis of an object’s Transform can get. You set yLimit to the cosine of the maximum angle (here, about 45 degrees).
using UnityEngine;
public class RollLimiter : MonoBehaviour
{
public float yLimit = .707f;
Quaternion prior;
void Start()
{
prior = transform.rotation;
}
void Update()
{
if ((transform.rotation * Vector3.up).y < yLimit)
{
transform.rotation = prior;
}
prior = transform.rotation;
}
}
Oh. Yeah, that would work, but it would require a bit of script modification, and I tend to not put too much faith into the people asking the questions. ;)
I'd rather assume that people usually need enough detail to answer the question in most cases, and can ask follow-up questions if they need more info, rather than trying to cover every possible situation upfront. MouseLook is pretty straightforward and everybody has it, so I didn't think there was a reason to paste the code here in this case.
Joels answer provides the best Solution, using the axis to first affect the rotation is the best way to demonstrate the clamp, thanks.
– skylemHi @joel_b , I had a related issue and came across this post while searching. Just wanted to say thanks for taking the time to write this, I've had an issue with Quaternions in the MouseLook script for a long time, but never altered they way I handled rotations until reading your
– animalphasetransform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, -rotationZ);line. After that I was able to make my force-player-look code work just fine without weird interactions with the Quaternion. So thanks for spurring on my thinking!Short, sweet, and effective! Thanks!
– SoldierofYHVHThere is a slight improvement that can be made to this. Instead of separating
– XenoRorotationZinto it's own variable, and then repeatingtranform.localEulerAngles._, you can use the fact thatVector_are structs, and passed-by-value. Just manipulate the finallocalEulerAnglesvector directly and then plug it back to the transform: var rotation = transform.localEulerAngles; rotation.z = Mathf.Clamp (rotation.z + Input.GetAxis("Mouse X") * sensitivityZ, -90, 90); transform.localEulerAngles = rotation;