Object rotation constraint problems with Mathf.Clamp ()

I am working on a game that rotates an object on the z axis. I need to limit the total rotation to 80 degrees. I tried the following code but it doesn't work. minAngle = -40.0f and maxAngle = 40.0f

Vector3 pos = transform.position;
pos.z = Mathf.Clamp(pos.z, minAngle, maxAngle);
transform.position = pos;

      

+3


source to share


2 answers


The code you posted clamps the z position. You want to use transform.rotation



void ClampRotation(float minAngle, float maxAngle, float clampAroundAngle = 0)
{
    //clampAroundAngle is the angle you want the clamp to originate from
    //For example a value of 90, with a min=-45 and max=45, will let the angle go 45 degrees away from 90

    //Adjust to make 0 be right side up
    clampAroundAngle += 180;

    //Get the angle of the z axis and rotate it up side down
    float z = transform.rotation.eulerAngles.z - clampAroundAngle;

    z = WrapAngle(z);

    //Move range to [-180, 180]
    z -= 180;

    //Clamp to desired range
    z = Mathf.Clamp(z, minAngle, maxAngle);

    //Move range back to [0, 360]
    z += 180;

    //Set the angle back to the transform and rotate it back to right side up
    transform.rotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, z + clampAroundAngle);
}

//Make sure angle is within 0,360 range
float WrapAngle(float angle)
{
    //If its negative rotate until its positive
    while (angle < 0)
        angle += 360;

    //If its to positive rotate until within range
    return Mathf.Repeat(angle, 360);
}

      

+7


source


Here's a static version of Imapler's nice solution, which, instead of changing the angle itself, returns a chamfered angle, so it can be used with any axis.

public static float ClampAngle(
    float currentValue,
    float minAngle,
    float maxAngle,
    float clampAroundAngle = 0
) {
    return Mathf.Clamp(
        WrapAngle(currentValue - (clampAroundAngle + 180)) - 180,
        minAngle,
        maxAngle
    ) + 360 + clampAroundAngle;
}

public static float WrapAngle(float angle)
{
    while (angle < 0) {
        angle += 360;
    }
    return Mathf.Repeat(angle, 360);
}

      

Or, if you don't expect to use the WrapAngle method, here's the all-in-one version:



public static float ClampAngle(
    float currentValue,
    float minAngle,
    float maxAngle,
    float clampAroundAngle = 0
) {
    float angle = currentValue - (clampAroundAngle + 180);

    while (angle < 0) {
        angle += 360;
    }

    angle = Mathf.Repeat(angle, 360);

    return Mathf.Clamp(
        angle - 180,
        minAngle,
        maxAngle
    ) + 360 + clampAroundAngle;
}

      

So now you can do:

transform.localEulerAngles.x = YourMathf.ClampAngle(
    transform.localEulerAngles.x,
    minX,
    maxX
);

      

+1


source







All Articles