我正在构建一个只能转向某些固定区域的旋钮。 现在我在其中一个区域使用数学钳:
float clampedAngle = Mathf.Clamp(angle, -250f, 0f);
我希望它适用于多个区域,例如:
clampedAngle = Mathf.Clamp(angle, -250f, -230f);
clampedAngle = Mathf.Clamp(angle, -100f, -45f);
clampedAngle = Mathf.Clamp(angle, -30f, 0f);
不幸的是,上面的代码不起作用,因为它会限制到最后一个值。如何将值钳制到多个有效区域?
答案 0 :(得分:0)
这个问题的棘手部分是确定要钳制的范围。一种方法是找到与该值绑定的最接近的最小值/最大值,然后根据相应的范围进行钳位。
假设您的范围表示为值对的数组(双值数组),我们可以将它们连接在一起,并通过调整this answer中的方法来找到最接近的最小/最大值。然后,相当容易向后工作以确定最小/最大值来自哪个范围,并相应地进行钳位:
// Clamps given value to nearest of given min/max pairs
private float ClampToNearestRange(float value, float[][] ranges)
{
// First, let's flatten the values into a single list
List<float> flattenedRanges = ranges.SelectMany(item => item).ToList();
// Now, we'll find the closest value in the list, and then get its index
float nearestValue = flattenedRanges.Aggregate((x,y) => Mathf.Abs(x-value) < Mathf.Abs(y-value) ? x : y);
int valueIndex = flattenedRanges.IndexOf(nearestValue);
// With the value index, we can deduce the corresponding range index
int rangeIndex = (valueIndex % 2 == 0) ? valueIndex / 2 : (valueIndex - 1) / 2;
// Finally, we'll clamp according to the range we selected
return Mathf.Clamp(value, ranges[rangeIndex][0], ranges[rangeIndex][1]);
}
然后您将使用如下方法:
// First, declaring your ranges somewhere in your class
float[] range1 = new float[]{0, 60};
float[] range2 = new float[]{80, 100};
float[] range3 = new float[]{150, 200};
float[][] ranges;
Start ()
{
ranges = new float[][]{range1, range2, range3};
float clampedAngle1 = ClampToNearestRange(120, ranges); // returns 100
float clampedAngle2 = ClampToNearestRange(126, ranges); // returns 150
float clampedAngle3 = ClampToNearestRange(170, ranges); // returns 170
}
注意:这确实使用LINQ,这意味着如果您需要经常这样做,您可能希望将逻辑扩展为更多Unity友好的循环。不会那么简洁,但它可能会影响你的游戏性能。
希望这有帮助!如果您有任何问题,请告诉我。