work vector3 unity mathf lerp how float does clamp01 c# clamp

c# - vector3 - mathf unity 5



¿Dónde puedo encontrar la función "abrazadera" en.NET? (7)

Me gustaría fijar un valor x a un rango [a, b] :

x = (x < a) ? a : ((x > b) ? b : x);

Esto es bastante básico. Pero no veo una función "abrazadera" en la biblioteca de clases, al menos no en System.Math .

(Para los desconocedores "sujetar" un valor es asegurarse de que se encuentra entre algunos valores máximos y mínimos. Si es mayor que el valor máximo, entonces es reemplazado por el máximo, etc.)



No hay uno, pero no es muy difícil hacer uno. Encontré uno aquí: clamp

Es:

public static T Clamp<T>(T value, T max, T min) where T : System.IComparable<T> { T result = value; if (value.CompareTo(max) > 0) result = max; if (value.CompareTo(min) < 0) result = min; return result; }

Y se puede usar como:

int i = Clamp(12, 10, 0); -> i == 10 double d = Clamp(4.5, 10.0, 0.0); -> d == 4.5


Puedes escribir un método de extensión:

public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T> { if (val.CompareTo(min) < 0) return min; else if(val.CompareTo(max) > 0) return max; else return val; }

EDITAR: los métodos de extensión van en clases estáticas, ya que se trata de una función bastante de bajo nivel, probablemente debería ir en algún espacio de nombres central en su proyecto. A continuación, puede utilizar el método en cualquier archivo de código que contenga una directiva de uso para el espacio de nombres, por ejemplo

using Core.ExtensionMethods int i = 4.Clamp(1, 3);

.NET Core 2.0

Comenzando con .NET Core 2.0 System.Math ahora tiene un método Clamp que se puede usar en su lugar:

using System; int i = Math.Clamp(4, 1, 3);


Simplemente compartiendo la solución de Lee con los problemas y preocupaciones de los comentarios, cuando sea posible:

public static T Clamped<T>(this T value, T min, T max) where T : IComparable<T> { if (value == null) throw new ArgumentNullException(nameof(value), "is null."); if (min == null) throw new ArgumentNullException(nameof(min), "is null."); if (max == null) throw new ArgumentNullException(nameof(max), "is null."); //If min <= max, clamp if (min.CompareTo(max) <= 0) return value.CompareTo(min) < 0 ? min : value.CompareTo(max) > 0 ? max : value; //If min > max, clamp on swapped min and max return value.CompareTo(max) < 0 ? max : value.CompareTo(min) > 0 ? min : value; }

Diferencias

Limitaciones: sin abrazaderas de un solo lado. Si max es NaN , siempre devuelve NaN (ver el comentario de Herman ).


Solo use Math.Min y Math.Max :

x = Math.Min(Math.Max(x, a), b);


Tratar:

public static int Clamp(int value, int min, int max) { return (value < min) ? min : (value > max) ? max : value; }


Usando las respuestas anteriores, la resumí en el código siguiente para mis necesidades. Esto también le permitirá fijar un número solo por su mínimo o máximo.

public static class IComparableExtensions { public static T Clamped<T>(this T value, T min, T max) where T : IComparable<T> { return value.CompareTo(min) < 0 ? min : value.ClampedMaximum(max); } public static T ClampedMinimum<T>(this T value, T min) where T : IComparable<T> { return value.CompareTo(min) < 0 ? min : value; } public static T ClampedMaximum<T>(this T value, T max) where T : IComparable<T> { return value.CompareTo(max) > 0 ? max : value; } }