- Home /
Min-Angle Constraint Script Causes Jitter
The relevant snippet is as follows:
public void LateUpdate()
{
float error = 0.0f;
float localZRot = transform.localRotation.eulerAngles.z;
if (Mathf.Sign(transform.localRotation.w) < 0)
localZRot = localZRot - 360;
if (localZRot < MinAngle)
{
error = MinAngle - localZRot;
}
else if (localZRot > MaxAngle)
{
error = MaxAngle - localZRot;
}
transform.Rotate(0.0f, 0.0f, error);
}
The script, as part of a MonoBehavior, is intended to limit the local rotation of a transform between two angles. Every LateUpdate, the function:
grabs the local rotation about the Z axis in the form of a Euler angle value [0, 359],
uses the sign of the quaternion's w component to determine whether the angle is to the left or right of 0 (that is, clockwise or counter-clockwise from Quaternion.Identity),
checks if the angle violates the minimum or maximum angle constraints and finally,
rotates the transform by the difference between the constraint and the actual rotation.
The function actually works as intended, rotating the transform back to the minimum or maximum angle whenever it violates the constraint. However, at random intervals, when satisfying the minimum angle constraint, the transform will jitter and its rotation will momentarily appear to be equal to the MaxAngle constraint before flashing back to the appropriate MinAngle. The inability to reliably reproduce this error given the same input makes me think this is some sort of funky side effect of using LateUpdate, but the docs make it seem like LateUpdate is the function to use if I want to override any changes to my transform that other calculations may have made. My questions are:
1. Is there anything in my code that might be causing this?
2. Is the fact that this function body appears in LateUpdate() the cause of my issue?
3. If so, how else can I reliably enforce rotational constraints on a transform?
Thanks in advance for the help!
EDIT: To make things even weirder, I've found that explicitly setting localRotation to a quaternion representing the MinAngle or MaxAngle rotation works perfectly, but the aforementioned Quaternion.Rotate() method causes the associated jitter. What is the reason for this? Is Quaternion.Rotate() not instantaneous?
For clarity, this is the updated function code that works flawlessly with no noticeable jitter:
public void LateUpdate()
{
float error = 0.0f;
float localZRot = transform.localRotation.eulerAngles.z;
if (Mathf.Sign(transform.localRotation.w) < 0)
localZRot = localZRot - 360;
if (localZRot < MinAngle)
{
transform.localRotation = Quaternion.AngleAxis(MinAngle, Vector3.forward);
}
else if (localZRot > MaxAngle)
{
transform.localRotation = Quaternion.AngleAxis(MaxAngle, Vector3.forward);
}
}