- Home /
Limiting rotation of an object
Hi,
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?
Answer by Eric5h5 · Jun 02, 2010 at 06:49 PM
Take a look at the MouseLook script in Standard Assets for a way of limiting rotation.
@Eric This would only apply if the cannon was in first-person mode.
@SpikeX: No, the principle is the same. You wouldn't actually use the $$anonymous$$ouseLook script, you'd use the angle-limiting bits.
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. $$anonymous$$ouseLook is pretty straightforward and everybody has it, so I didn't think there was a reason to paste the code here in this case.
Thanks a lot! It works, although I'm not exactly sure how. :P
Like SpikeX correctly assumes I don't have a lot of coding experience so all those quaternions and so on were a bit hard to wrap my head around.
Anyway, Thanks a lot! I wouldn't have figured it out without your help!
Answer by joel_b · May 24, 2013 at 02:16 AM
You can use the same code from MouseLook.cs. The following code will lock rotation between -90 and 90 degrees in the Z-axis.
Here is an example:
// gobal
private float rotationZ = 0f;
private float sensitivityZ = 2f;
void lockedRotation()
{
rotationZ += Input.GetAxis("Mouse X") * sensitivityZ;
rotationZ = Mathf.Clamp (rotationZ, -90, 90);
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y, -rotationZ);
}
$$anonymous$$s answer provides the best Solution, using the axis to first affect the rotation is the best way to demonstrate the clamp, thanks.
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 $$anonymous$$ouseLook 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. Ins$$anonymous$$d 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 = $$anonymous$$athf.Clamp (rotation.z + Input.GetAxis("$$anonymous$$ouse X") * sensitivityZ, -90, 90);
transform.localEulerAngles = rotation;
Answer by pset · Jul 25, 2017 at 02:00 PM
You can use quaternion function Quaternion.RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta) to restrict rotation like this:
Quaternion ClampRotationXByLookDirection(Quaternion curentRotation)
{
Vector3 lookDirectionX = Vector3.ProjectOnPlane(lookDirection, Vector3.right).normalized;
Quaternion lookRotation = Quaternion.LookRotation(lookDirectionX);
Quaternion towardsRotation = Quaternion.RotateTowards(lookRotation, curentRotation, lookDeltaX);
return towardsRotation;
}
Quaternion ClampRotationYByLookDirection(Quaternion curentRotation)
{
Vector3 lookDirectionY = Vector3.ProjectOnPlane(lookDirection, Vector3.up).normalized;
Quaternion lookRotation = Quaternion.LookRotation(lookDirectionY);
Quaternion towardsRotation = Quaternion.RotateTowards(lookRotation, curentRotation, lookDeltaY);
return towardsRotation;
}
Answer by qJake · Jun 02, 2010 at 06:56 PM
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 $$anonymous$$=-30, max=30 either. It's generally better to track rotations yourself, like the $$anonymous$$ouseLook script does. (Just to nitpick, transform.rotation.eulerAngles is redundant; you only need transform.eulerAngles.)
Ah, didn't know that. Is there some better way of limiting like this (using Update) than using the euler angles?
@SpikeX: Yes, use your own variable for tracking the rotation in combination with a ClampAngle function, and apply that to the transform, like $$anonymous$$ouseLook 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 = $$anonymous$$athf.Clamp(localEuler.z, $$anonymous$$, max);
transform.localEulerAngles = localEuler;
As a (way) more experienced programmer, are there any pitfalls you can see with something like that?
Answer by blented · Oct 03, 2015 at 02:37 PM
You can use Quaternion.Slerp()
to limit the rotation of an object, for instance:
transform.localRotation = Quaternion.Slerp(rot, Quaternion.Euler(Vector3.forward), limit);
This would blend between Quaternion rot and forward based on limit.