Проблемы ограничения поворота объекта с помощью Mathf.Clamp()
Я работаю над игрой, которая вращает объект по оси Z. Мне нужно ограничить общее вращение до 80 градусов. Я попробовал следующий код, но он не работает. minAngle = -40.0f и maxAngle = 40.0f
Vector3 pos = transform.position;
pos.z = Mathf.Clamp(pos.z, minAngle, maxAngle);
transform.position = pos;
2 ответа
Решение
Код, который вы разместили, ограничивает позицию z. То, что вы хотите, это использовать 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);
}
Вот статическая версия приятного решения от Imapler, которое вместо изменения самого угла возвращает заданный угол, поэтому его можно использовать с любой осью.
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);
}
Или, если вы не собираетесь использовать метод WrapAngle, вот версия " все в одном":
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;
}
Итак, теперь вы можете сделать:
transform.localEulerAngles.x = YourMathf.ClampAngle(
transform.localEulerAngles.x,
minX,
maxX
);