Trigonometría con Mathf Hola a todos, Me dispongo a hacer unas explicaciones de trigonometría
Mathf y como funciona, y algo de explicaciones matematicas al respecto. Explicare los metodos mas importantes de la trigonometría.
Explicare primero los arcos de coseno, seno y tangente. explicando en ellos el coseno, seno y tangente a su vez. luego mostrare como funciona Mathf.cos, Mathf.sin y Mathf.tan aparte sin explicar matematicamente cada uno, ya que han sido explicados junto a sus arcos.
Mathf.Abs Este es sencillo y facil de entender asi que no me entretengo, Abs retorna el valor absoluto de un valor X
Debug.Log(Mathf.Abs(-2045.34f));
//Vemos que estamos pasando el valor -2045.34f, el valor retornado sera 2045.34
//Si el valor que le pasamos a Mathf.Abs() es -10, este nos retornara 10.
//En definicion, Abs retornara el valor positivo.
Mathf.Acos Esta devuelve el
Arcocoseno de un valor, recordar que lo devuelve en
radianes.
Que es
coseno: Quiero explicar antes el
coseno para poder entender mejor el
arcocoseno. (Al igual que haré con
seno, el codigo de ejemplo lo pondre para
Mathf.Cos())
(https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Trigono_b00.svg/280px-Trigono_b00.svg.png)
el coseno es la razon entre: El cateto adyacente (b) a dicho ángulo y la hipotenusa (c) en un triangulo rectangulo.
esto quiere decir que
cos α = b / c donde α es el valor angular con un dominio de [0,π]. (cuando hablamos de dominio, queremos decir un rango entre un minimo y un maximo, en este caso el minimo es 0 y el maximo 3.14159265359)
Esta es la grafica de coseno: (https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Cosine.svg/590px-Cosine.svg.png)
Que es Arcocoseno: Por definicion es la funcion recíproca de coseno, Esta es el arco cuyo coseno es alfa.
(https://upload.wikimedia.org/wikipedia/commons/thumb/9/98/Arccos.svg/300px-Arccos.svg.png)
arcocoseno restringe el dominio de la funcion coseno a (x) [-1,1] donde su codominio (α) [0, π].
Donde x es el valor comprendido entre -1 y 1 de la linea que vemos en la imagen, y α es la aceleración angular por unidad de tiempo.
float x = ; //0 es exactamente es exactamente la bisectriz del primer y el tercer cuadrante de la grafica de arcocoseno.
Debug.Log(Mathf.Acos(x));
//Devolvera (1/2)π radianes, que es 1,57 radianes. que en grados es 0.
//Si X fuese 0.7, Devolveria (1/4)π radianes, que es 0,785 radianes. que son 45 grados.
La tabla de valores comunes es:
Valor dominio X: -1 -√2/2 -1/2 0 1/2 √2/2 1
Angulos: 180 135 120 90 60 45 0
Radianes: π 3/4π 5/6π 1/2π 1/3π 1/4π 0
Que son Radianes:
El radian es la unidad de ángulo plano, en el sistema de medidas, 1rad = r. donde r es el radio de la circunferencia. y la circunferencia siempre vale 2π radianes. Esto quiere decir que 1 radian en valor decimal es equivalente la la longitud del radio. os dejo una imagen que aclara bastante la mente.
(https://upload.wikimedia.org/wikipedia/commons/thumb/4/4e/Circle_radians.gif/300px-Circle_radians.gif)
Mathf.Approximately
Segun la referencia oficial de unity: (Este metodo lo añado por que me parecia interesante)
Compara dos valores de punto flotante si son similares.
Debido a la imprecisión del punto flotante no se recomienda comparar los flotantes usando el operador igual. p.ej. 1.0 == 10.0 / 10.0 puede no devolver true.
[/quote]
//En vez de:
if(1.0f == 10.0f / 10.0f)...
//Hacer esto:
if(Mathf.Aproximately( 1.0f, 10.0f / 10.0f )...
(Supongo que esto es mejor usarlo con valores float largos como pueda ser π.)
Mathf.Asin
Este metodo devuelve el arcoseno de un valor, Recordar que lo devuelve en Radianes.
Que es seno: Como con arcocoseno ya explique el coseno, con arcoseno explicare el seno.
(https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Trigono_b00.svg/280px-Trigono_b00.svg.png)
el seno es la razon entre: El cateto opuesto (a) a dicho ángulo y la hipotenusa (c) en un triangulo rectangulo.
esto quiere decir que sen α = a / c (La diferencia con coseno es que coseno usa cateto adyacente, y este usa el opuesto al ángulo)
donde α es el valor angular con un dominio de [0,π].
Esta es la grafica de seno:(https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Sine.svg/350px-Sine.svg.png)
Ahora que sabemos que es el seno:
La curva del coseno (antes vista) es la curva del seno desplazada (https://wikimedia.org/api/rest_v1/media/math/render/svg/98f98bef5d4981ff6e2aa827d4699e347fb30db2) a la izquierda dando lugar a la siguiente expresión:
(https://wikimedia.org/api/rest_v1/media/math/render/svg/0a66aa9807eb8b889dc9f8cce78cb1b10f75801a)
[/quote]
Que es Arcoseno: Al igual que arcocoseno es la funcion recíproca de coseno, arcoseno es la funcion recíproca de seno. Lo que quiere decir que: SI arcsen x = α ENTONCES sen α = x
recordar tambien que se escribe arcsen o sen-1
Es el arco cuyo seno es α.
(https://upload.wikimedia.org/wikipedia/commons/thumb/5/54/Arcsin.svg/300px-Arcsin.svg.png) (Es como el espejo de arcocoseno antes explicado)
arcoseno restringe el dominio de la funcion seno a (x) [-1,1] donde su codominio (α) [-π/2, π/2].
Os mostrare ahora una imagen de como se comportan seno y arcoseno en una grafica:
(http://www.universoformulas.com/imagenes/matematicas/trigonometria/grafica-arcoseno-simetrica-seno.jpg) La gráfica de la función arcoseno es simétrica a la de la función seno respecto a la recta bisectriz del primer y tercer cuadrante (y=x)
float x = .5f; //.5f es el equivalente a 1/2
Debug.Log(Mathf.Asin(x)); //Devolvera 1/6π radianes que es 0,52 y son 30 grados.
Mathf.Atan
El metodo devuelve en arcotangente de un valor, recordar que lo devuelve en radianes.
Que es la Tangente: La tangente la razon entre los catetos de un triangulo rectangulo.
(https://upload.wikimedia.org/wikipedia/commons/thumb/5/5f/Trigono_b00.svg/280px-Trigono_b00.svg.png)tan α = a / b Siempre como dividendo es el cateto opuesto, y como divisor el cateto adyacente.
Vamos a recordar que sen α = a / c y que cos α = b / c por lo tanto la tangente de α se puede expresar como tan α = sen α / cos a
(http://www.universoformulas.com/imagenes/matematicas/trigonometria/representacion-geometrica-tangente.jpg)
Para comprender el concepto de tangente, graficamente vista en la imagen anterior, imagina una linea que su punto 0 nace desde D y tiende a infinito.
El dominio de la tangente es (x) [-∞,∞], donde su codominio (α) [-π/2, π/2].
(Tranquilos esta funcion no estan necesaria en un principio como seno y coseno, asi que no os preocupeis si os resulta mas compleja)
Que es Arcotangente: En este caso es la función recíproca de tangente.
(http://www.universoformulas.com/imagenes/matematicas/trigonometria/grafica-arcotangente.jpg)
Al igual que con arcoseno y arcocoseno, arcotangente es el arco cuya tangente es α.
En notacion matematica se puede escribir arctan o tan-1.
Uso con unity de estas funciones
Vale, ahora que sabemos la teoria, queda lo mas interesante que es la practica de estos conceptos en unity, y aplicaciones varias.
El metodo que utilizare para mostrar los ejemplos sera con imagenes y codigo para que veamos la facilidad del asunto. (Recordar tambien que el objetivo es entender estos conceptos, para que podais usarlos a vuestro libre albederio)
En este ejemplo, vamos a ver como saber los grados que tiene que rotar un objeto para mirar a otro. (Aunque esta funcion ya trae incorporada unity como Transform.LookAt() aquí explicare como funciona internamente)
Lo primero que hay que saber es como conseguir la distancia entre dos puntos del plano de unity. (Yo trabajare con Vectores de dos dimensiones, "Vector2")
Vector2.Distance(Vector2 a, Vector2 b); //Distancia entre los dos vectores.
//Es lo mismo que hacer:
Vector2 a = new Vector2(10, 11);
Vector2 b = new Vector2(5, 8);
float dist = (a - b).magnitude;
Debug.Log(dist);
Ahora en el proyecto creamos dos objetos, recuerdo que estoy trabajando en 2D, en 3D seria lo mismo pero jugando con Vector3, recordar que solo rotamos en el eje Y.
Como vemos he creado dos objetos en un plano bidimensional, son dos sprites, el azul llamado objeto1 su posicion es: X=0 Y=-3.5, el negro y rojo llamado objeto2 su posicion es X=4 Y=-1.
Como veis he dibujado un triangulo rectangulo a partir del punto A (Objeto1) y punto B (Objeto2) ahora tenemos la incognita de C que es sencilla, es la posicion Y de A y la posicion X de B
Para encontrar la posición de C en Unity:
public Transform A, B;
//Aqui añadiremos los objetos de nuestra escena desde el inspector.
void Start () {
Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1
}
Ahora ya tenemos los 3 puntos de nuestro triangulo imaginario. Ahora hay que saber la distancia de h, de ca y de co
Aunque para sacar el coseno que es lo que necesitamos, no nos hacefalta co, ya que solo necesitamos cateto adyacente e hipotenusa.
public Transform A, B;
//Aqui añadiremos los objetos de nuestra escena desde el inspector.
void Start () {
Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1
float h = (A.position - B.position).magnitude; //Distancia de hipotenusa
float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente
float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto.
}
Sacaremos ahora el coseno del triangulo, para que nos de los radianes.
public Transform A, B;
//Aqui añadiremos los objetos de nuestra escena desde el inspector.
void Start () {
Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1
float h = (A.position - B.position).magnitude; //Distancia de hipotenusa
float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente
float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto.
//Sabiendo que; cos α = ca / h
float a = ca / h; //Ya tenemos alfa.
float rad = Mathf.Cos(a); //ahora sacamos con Mathf el coseno de alfa y lo pasamos a una variable float, que sera el valor en radianes.
Debug.Log(rad); //Nos dara 0.66
}
Vale ahora tenemos el valor en radianes, ahora lo pasaremos a grados.
public Transform A, B;
//Aqui añadiremos los objetos de nuestra escena desde el inspector.
void Start () {
Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1
float h = (A.position - B.position).magnitude; //Distancia de hipotenusa
float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente
float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto.
//Sabiendo que; cos α = ca / h
float a = ca / h; //Ya tenemos alfa.
float rad = Mathf.Cos(a); //ahora sacamos con Mathf el coseno de alfa y lo pasamos a una variable float, que sera el valor en radianes.
//Para pasar de radianes a grados es aplicar la regla de 3
//-> Pi / 180 = rad / X despejamos la x
// y la ecuacion es-> x=180*rad/Pi
float grados = (180 * rad) / Mathf.PI;
Debug.Log(grados);
}
No os equivoqueis por que estos no son los grados que hay que rotar, estos son los a los que se encuentra el punto B respecto al punto A, os muestro una imagen para que lo comprendais.
Si nuestro sprite mirase a la derecha por defecto (que es donde comienda el grado 0) entonces 37.9 grados serian los que tendria que rotar a su izquierda, pero nosotros tenemos el offset de 90 grados por que nuestro sprite mira hacia arriba. (Por eso hay que hacer un pequeño arreglo)
Y ahora si por fin lo rotaremos lo necesario para que mire hacia el otro objeto.
void Start () {
Vector2 C = new Vector2(B.position.x, A.position.y); //C es la posicion X del objeto2 y la posicion Y del objeto 1
float h = (A.position - B.position).magnitude; //Distancia de hipotenusa
float ca = (new Vector2(A.position.x, A.position.y) - C).magnitude; //distancia cateto adyacente
float co = (new Vector2(B.position.x, B.position.y) - C).magnitude; //distancia cateto opuesto.
//Sabiendo que; cos α = ca / h
float a = ca / h; //Ya tenemos alfa.
float rad = Mathf.Cos(a); //ahora sacamos con Mathf el coseno de alfa y lo pasamos a una variable float, que sera el valor en radianes.
//Para pasar de radianes a grados es aplicar la regla de 3
//-> Pi / 180 = rad / X despejamos la x
// y la ecuacion es-> x=180*rad/Pi
float grados = (180 * rad) / Mathf.PI;
float offset = 90; //Este es el offset de nuestro sprite, por que por defecto deberia de mirar a izquierda y no arriba.
//Ahora ya si, lo rotamos
A.Rotate(new Vector3(,,-(offset-grados)));
}
Recordar que el offset cambia segun si esta a izquierda o derecha de nosotros, tambien segun este arriba o abajo.
Esto es un ejemplo de una de las muchas utilidades de la trigonometría en los videojuegos, esta claro que para muchos unity ya da herramientas, pero para otros no, por eso estos conceptos son necesarios saberlos.
Un saludo y espero que les sirva esta pequeña explicación!
Excelente :) Muchas gracias!
Muy buen trigonotutorial! , yo hubiera agregado algo que se usa mucho que son las sinusoides temporales, como el efecto de "camera bobbing", y tambien en shaders como el efecto wave. Ejemplo:
cam. y += amplitud * Mathf.Sin(time * frecuencia + fase);
time += Time.deltaTime;
Gracias por el aporte
Me alegro que les guste muchachos, @lightbug queria añadir mas cositas pero por tiempo y longitud del post lo dejare para otra ocasion, muchas gracias!
Wow. Menudo curro te has pegado.
Muchisimas gracias,mañana le pegare un repaso.
@hammer gracias tio, me alegro que te guste, espero te sirva y un saludo!
Muchas Gracias por el aporte.