Jump to content
kingtrase

Trigonometría con Mathf en Unity

Recommended Posts

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())

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: 590px-Cosine.svg.png

 

Que es Arcocoseno: Por definicion es la funcion recíproca de coseno, Esta es el arco cuyo coseno es alfa.

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.

300px-Circle_radians.gif

Mathf.Approximately

Segun la referencia oficial de unity: (Este metodo lo añado por que me parecia interesante)

Cita

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.

//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.

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:350px-Sine.svg.png

Ahora que sabemos que es el seno: 

Cita

 

La curva del coseno (antes vista) es la curva del seno desplazada a la izquierda dando lugar a la siguiente expresión: 

 

 

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 α.

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:

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.

280px-Trigono_b00.svg.pngtan α = 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

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.

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.

Sin nombre.png

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.

Sin nombre.png

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!

 

    Edited by kingtrase
    • Like 1

    Share this post


    Link to post
    Share on other sites

    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

    Share this post


    Link to post
    Share on other sites

    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!

    Share this post


    Link to post
    Share on other sites

    UnitySpain © Todos los derechos reservados 2020
    ×
    ×
    • Create New...