Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation since 12/24/2020 in all areas

  1. 3 points
    tienes que buscar un poco antes de preguntar, probar si puedes hacerlo mínimo 2 días y sino preguntas, tu pregunta esta en el manual lee un poco. URL: https://docs.unity3d.com/ScriptReference/Rigidbody-isKinematic.html Controla si la física afecta al cuerpo rígido. Si isKinematic está activado, las fuerzas, colisiones o articulaciones ya no afectarán al cuerpo rígido. El cuerpo rígido estará bajo control total de animación o control de script cambiando transform.position. Los cuerpos cinemáticos también afectan el movimiento de otros cuerpos rígidos a través de colisiones o articulaciones. Eg. puede conectar un cuerpo rígido cinemático a un cuerpo rígido normal con una articulación y el cuerpo rígido se restringirá con el movimiento del cuerpo cinemático. Los rigidbodies cinemáticos también son particularmente útiles para hacer personajes que normalmente son impulsados por una animación, pero en ciertos eventos se pueden convertir rápidamente en un ragdoll estableciendo isKinematic a false. using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { public Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } // Let the rigidbody take control and detect collisions. void EnableRagdoll() { rb.isKinematic = false; rb.detectCollisions = true; } // Let animation control the rigidbody and ignore collisions. void DisableRagdoll() { rb.isKinematic = true; rb.detectCollisions = false; } } este es un ejemplo básico solo para la colisión y estado muerto del enemigo, si quieres chocar al enemigo y que las físicas interactúe con el enemigo muerto tienes que hacer un Ragdoll del enemigo para desactivar la animación del enemigo y que cuando tenga 0 de vida se caiga y lo puedas mover cuando colisionas con el. public void Ejemplo(float amount) { if (health < 5) //este valor depende de cuanto daño le haces al enemigo., lo que dice es si vida es menor a 5 pasa a estado de muerte. { muerte(); } } void muerte() { Destroy(GetComponent<NavMeshAgent>()); // aca se desactiva la inteligencia Artificial. anim.enabled = false; //aca desactiva la animacion quedando solo el Ragdoll. } sino sabes que es un Ragdoll acá te dejo un link :"" https://www.youtube.com/watch?v=DInV-jHm9rk&t=1s¨
  2. 3 points
    necesito ayuda! no se si esto funcionara foreach (User _user in UnitySpainUserList) { _user.addMessage("felices fiestas"); }
  3. 2 points
    Curioso que muestres la imagen que aparece en el manual, donde realmente está la solución: https://docs.unity3d.com/Packages/com.unity.ugui@1.0/manual/script-SelectableNavigation.html La opción Visualize está activa. Unity Learn para el UI Navigation: https://learn.unity.com/tutorial/ui-navigation#
  4. 1 point
    Hola, comunidad! buenas tardes. Quiero compartir con ustedes un proyecto en el que trabaje prácticamente 5 meses continuos y a su vez, realizarles una pregunta para qué puedan guiarme y elegir sabiamente. El juego se llama "Club del fierro" se encuentra disponible en playstore, actualmente 27k lo han descargado (es lo que me marca la ficha) comparto algunas imágenes: El juego se trata de picadas(como le decimos aquí en argentina), o mejor como arrancones, piques, drag etc. en el mismo, uno puede modificar los autos (piezas, colores, partes, mecánica básica y avanzada por puntos, altura etc.), correr contra bots, o en una tabla global online para ver quien tiene el mejor tiempo a nivel mundial... ¡Volviendo al juego, estoy por integrar partidas online con Photon! Próximamente saldrá la versión online, que tantos usuarios están esperando (administro un grupo en fb llamado "club del fierro (comunidad del juego oficial), el cual tiene 7.3 usuarios y aproximadamente 600 a 900 usuarios activos por día) ¡Aclaro que al juego le invertí 0 publicidad paga! se corrió la noticia de boca en boca y aún siguen instalando, descargando y uniéndose a la comunidad! Link del juego por si quieren probarlo: https://play.google.com/store/apps/details?id=com.club.f1&hl=es_AR&gl=US por si quieren ver algunos videos, algunos usuarios ya han creado cuentas en YouTube para enseñar el juego: esta es la que siempre recomiendo: me siento muy contento porque el juego se esta jugando mucho! te llena de energías ver tu proyecto terminado y siendo usado por muchos usuarios!
  5. 1 point
    Lo resolví bakeando todo de nuevo despues de un par de veces, nose que pasaría.
  6. 1 point
    Ah ostras! No te había entendido, gracias @francoe1 y @lightbug, desde luego no tengo tanto conocimiento o no lo había enfocado así, le doy una vuelta 👍
  7. 1 point
    Es probable que puedas "engañar" al sistema creando events por código. https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Events.html El ejemplo de la página (necesitas usar el namespace InputSystem.LowLevel) // Send event to update leftStick on the gamepad. InputSystem.QueueDeltaStateEvent(Gamepad.current.leftStick, new Vector2(0.123f, 0.234f) ); Quizás puedas reemplazar esto por Mouse.current, recuerdo que lo hice en su momento. De argumento le pasas la posición actual. No se si sea la mejor solución, es probable que si necesitas actualizar frame a frame UI no sea lo más efectivo, no lo se.
  8. 1 point
    no, ese no es el problema, el problema es que el raycaster deja de disparar cuando dejas de mover el ratón y dispara al moverlo de nuevo, entonces si dejo el ratón sin mover y al rato pasa una unidad que tiene El Evento IPointerEnter, no salta el evento ya que no se hace el raycast cuando esta el mouse parado parece.
  9. 1 point
    Buenas! Este es mi proyecto... Se trata de una experiencia audiovisual interactiva inmersiva mas que de un videojuego al uso. Es una aventura un tanto surrealista donde nuestro protagonista no sabe muy bien si lo que sucede es real, o un sueño y va adentrándose en un mundo cada vez mas extraño desentrañando poco a poco el misterio que mismo encierra. Quien haya jugado los dos anteriores Aporía hechos con Entidad 3D va a encontrar que este juego no pretende ser una continuación ni precuela de aquellos.... Este será mas bien como un reboot, manteniendo el espíritu jugable y el universo similar, pero yendo a terrenos un poco mas artísticos e inmersivos. Les dejo el primer avance:
  10. 1 point
    Beach Race Android Es de mi placer presentarles Beach Race, un endless runner donde debes evitar chocar ante algunos conductores que posiblemente se encuentren bajo los efectos de algún tipo de alcohol. Si es de agrado favor de dejar una Review. Que lo disfruten mucho. Gracias y mucha suerte en sus proyectos gente
  11. 1 point
    Me recuerda al Spy Hunter. Felicidades por publicar el proyecto.
  12. 1 point
  13. 1 point
    Tenes que usar "root motion", nada mejor que la documentación de Unity Unreal para explicar esto (mirá los videos de abajo): https://docs.unrealengine.com/en-US/AnimatingObjects/SkeletalMeshAnimation/RootMotion/index.html No es tan fácil, tenés que usar un hueso raíz (de ahí el root) que será el padre de los demas huesos (los deformables, no los de ayuda como pueden ser los IK) y además deberá contener la información del desplazamiento lineal/angular, es decir, tendrás que animar este hueso de tal manera de que represente el movimiento/rotación de tu personaje. En unity root motion se usa de dos maneras: Dándole a "Apply root motion" en el Animator. El Animator mueve a tu transform/rigidbody automaticamente. Extrayendo los datos del desplazamiento y re-aplicandolos (si fuera necesario) usando OnAnimatorMove. El animator, en este caso, te marca "handled by script". Aclaro: Root motion no es algo que debas hacer, como dijo @Igor probablemente con animaciones in-place sea más que suficiente (y procesar el desplazamiento/rotación dentro de un script). No se qué es realmente lo que intentas hacer.
  14. 1 point
    ya hemos enviado un sicario hacia tu casa
  15. 1 point
    el personaje, en la animacion, deveria estar siempre en el centro, sin moverse. y luego moverlo lo que corresponda en unity
  16. 1 point
    De entrada no deberías usar versiones tan nuevas como la 2020.1 si no quieres problemas de compatibilidad. He leído el texto tuyo de errores y aparece esto: > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade > Failed to read key mastereal from store "C:\Users\IUser\Desktop\Android Game\user.keystore": Cannot recover key O la referencia al fichero de claves de la keystore no es correcta, o la clave correspondiente al proyecto no está en esa keystore.
  17. 1 point
    Que bueno leer a alguien de E3d por aquí! Que usuario tenías en el foro? Gracias por el apoyo! El video dice poco y nada, pero pronto mostraré unos avances nuevos que van a dejar un poco mas claro por donde va el juego... Va a ser mas similar al Aporía 1 que al 2... mas laberitos (sin paredes ni techo, en su mayoría) mas plataformas y mucha exploración libre. El componente puzzle en el que se basa la jugabilidad de Aporía 2 con todo aquel rollo de los portales aquí va a ser mucho menor y va a estár implementado de manera diferente. Un abrazo!
  18. 1 point
    Hola gente como les va? Espero que muy bien... mi consulta es porque yo tengo un .mp4 que es el sonido de mis partículas, en este caso fuego, y quería saber como hacer para que se escuche al momento de que el fuego aparezca. Gracias saludos.
  19. 1 point
    Si el collider no está asociado a un sprite renderer (en el caso de 2d) no se ajustará a tamaño. Tendrás que hacerlo a mano con el size.
  20. 1 point
    @francoe1 él sapeee 🧙‍♂️🙌
  21. 1 point
    Pon todo el código que referencie ese gameobject o ves desactivando otros gameobjects hasta que no ocurra y descubras cual lo hace. Por lógica tiene que haber algo que lo desactive.
  22. 1 point
    Viendo el archivo de error.txt creo que pueden ser dos cosas: 1. No está actualizada la versión de .NET en Windows 2. No instalaste el JDK y NDK de Android a través de Unity Hub y no corresponde con la versión. Nada de Android Studio, tiene que ser a través del Hub.
  23. 1 point
    por lo que leído hay muchas razones por la que puede salir ese error. 1- unity no tiene los permisos necesarios de ejecución para el UnityLinker.exe, la solución seria ejecutar unity como administrador. 2- pude que sea un error en ASCII del nombramiento del juego como las escenas si coloco en algún momento ej : Exaple_1 eliminar el "_ " podría solucionarlo. 3- versión vieja del Net Framework actualice su versión eso debería corregirlo. 4- Asegúrese de que el nivel de compatibilidad de Api está establecido en .net 4.x. hay muchas mas razones pero creo que estas son las mas probables.
  24. 1 point
    😀 Por fin, las dos primeras partes de «Manos en la Sombra»: publicadas Todavía me faltan corregir cuatro partes más. Pero poco a poco.
  25. 1 point
    Chequea el modificador decimate (creo que significa diezmar):
  26. 1 point
    Ni idea de la Windows Store. Pero vamos, si te dice que no puede ser mayor de x bytes, pues nada, a ajustarlo en tamaño. No le veo complicación.
  27. 1 point
    Jajajjaja felices fiestas!!
  28. 1 point
  29. 1 point
    igualmente pásenla bien les deseo lo mejor a todos 🎅💖🥂
  30. 1 point
    hola, por que no pruebas a ir poco a poco primero que tu personaje reciba daño y después le vas añadiendo lo que veas que necesitas la animación etc... También prueba a hacer algún Debug.Log(); por si acaso no entra en algún OnCollision no te detecta algo y probar que se ejecute todo correctamente.
  31. 1 point
    tubproblema podria ser por muchas razones. y como no has explicado el funcionamiento de esas colisiones no podemos ayudarte. como derectas si hay colision con el arma? es con "triggers" (onTriggerEnter)? usas raycast? o usas onCollisionEnter? has ajustado las colisiones en propiedades/physics? usas diferentes capas? el player usa rigidBody? etc...
  32. 1 point
    Creo que no te responden porqué la pregunta es demasiado genérica y sin pistas más detalladas de lo que estás haciendo. Tal vez poniendo ejemplos del código y explicando qué haces puedas conseguir respuestas.
  33. 1 point
    Muchos lo sabréis y otros no, pero hay una lista de recursos bastante tocha hecha en zeef.com de recursos para el desarrollador de videojuegos. Espero que os sea de utilidad! https://game-development.zeef.com/daniel.cuadrado.gonzalez
  34. 1 point
    En la anterior entrada hablé sobre trigonometría, repasando las razones trigonométricas y viendo el teorema de pitágoras. Si no lo recuerdas o has llegado nuevo aquí, míralo antes de continuar (enlace debajo). Trigonometría Vectores Matrices Funciones Introducción Si estás familiarizado con motores de videojuegos como Unity, conocerás el concepto de vector ya que se usa habitualmente. Pero ¿qué es realmente un Vector? Un vector básicamente es una flecha que apunta en una dirección y que tiene una longitud concreta: Esto sería un ejemplo de un vector y cualquier flecha apuntando en cualquier dirección sería otro ejemplo. Pero ¿cómo representamos esto? Para poder hacerlo tenemos que llevarnos nuestro vector a un sistema de coordenadas (x e y) y establecer el origen del vector en el centro del sistema. Por si no recuerdas que era un sistema de coordenadas, es una forma de visualizar un punto en el espacio. En este caso el espacio es 2D por lo que se representa con dos líneas, una horizontal (representado por el valor X) y otra vertical (representado por el valor Y) que se cruzan en un punto, llamado centro: Así quedaría nuestro vector anterior dentro de un espacio de coordenadas. Esto, por ejemplo, podría representar el movimiento de una nave en su proceso de despegue. Comienza en la posición (0,0) y sigue en la dirección del vector hasta llegar a su objetivo. Teniendo en cuenta que X es el valor horizontal e Y el valor vertical, el vector sería (2,1) Pero ¿qué podemos hacer con esto? Como has visto puedes representar movimientos con ellos, por ejemplo. Pero para ver de forma práctica su uso vamos a usar Unity3D. Cualquier versión te servirá para este propósito puesto que solo vamos a tocar código básico. En mi caso usaré la versión 2020.1. Si usas otro motor la teoría sigue siendo válida pero tendrás que buscar la forma de adaptarlo por tu cuenta. Unity internamente usa vectores para colocar un objeto dentro de la escena (realmente esto es incorrecto ya que usa una matriz, pero no nos adelantemos). Si vas al componente Transform (crea un gameobject nuevo si no tienes ninguno) te encontrarás con este Vector3 (un estructura propia de Unity) que contiene 3 valores: Estos son la posición en X,Y,Z. Pero ¿pero qué son estos valores? Pues al igual que la gráfica anterior nos indican que desde el centro del mundo hasta la posición de este objeto el vector es (0,0,0). Vamos a ver qué podemos hacer con esto. Para ello creamos un objeto de nombre Player y otro de nombre Target. Los colocamos en diferente posición y le asignamos diferentes iconos para poder diferenciarlos: Recuerda que puedes cambiar el icono en la siguiente pestaña: Una vez hecho esto vamos a crear un nuevo script de nombre Player y lo vamos a añadir al objecto Player. En este script vamos a añadir una variable Transform pública de nombre target y vamos arrastrar nuestro Target a través del inspector. Con esto tendremos acceso al vector de posición del Target desde nuestro Player. Ya tenemos acceso a los dos vectores de posición, el del personaje y el del objetivo. Sabiendo esto ¿cómo hacemos que el personaje se mueva hacia el objetivo usando vectores? Pues aquí llega la parte interesante ya que si restas el vector de posición del objetivo con el vector de posición del personaje, el resultado es el vector necesario para llevar el player al objetivo. Veámoslo gráficamente creando la siguiente función: Si pulsamos play al añadir este código, veremos cómo el personaje se mueve hasta la posición del objetivo. Vale parece que se mueve, pero quiero más. ¿Que tal si medimos la distancia que hay entre uno y otro antes de moverlo? Para esto vamos a recordar la trigonometría que aprendimos en la parte anterior. Magnitud La magnitud de un vector es la distancia que hay entre dos puntos. En nuestro caso sería la posición del personaje y nuestro objetivo. Para calcularla solo tenemos que aplicar la fórmula de la distancia. Esta fórmula es simplemente el teorema de pitágoras disfrazado, y lo vamos a ver en la siguiente imagen: Como puedes ver, nosotros lo que queremos calcular es la distancia (h) por lo que podemos convertirlo en un triángulo añadiendo X e Y. Ahora solo tenemos que usar pitágoras para despejar h. ¿Lo recuerdas? Vamos a resolverlo en código. Para ello vamos a crear una clase estática nueva llamada BasicMath donde vamos a ir añadiendo nuestras funciones matemáticas a partir de ahora. Seguiremos usando Mathf (Unity) o Math (System) para realizar las operaciones básicas que se salen del objetivo de este tutorial. Mencionar que todos los cálculos e igualdades que haremos aquí serán basados en 2 dimensiones. Una vez se han entendido correctamente los cálculos, solo hay añadir la componente z. Esta sería nuestra implementación del teorema de pitágoras. Para ver la distancia simplemente podemos añadir un log en nuestra función MoveToTarget: Si estás familiarizado con Unity ya sabrás que por defecto nos soluciona todos los problemas de vectores con su estructura Vector. Podemos acceder directamente a la magnitud de un vector desde dentro del mismo de la siguiente forma: Como puedes ver, ambos resultados son iguales, aunque nuestra implementación es menos óptima que la que usa internamente Unity. Por lo que esta clase BasicMath y todo lo que contenga es únicamente para uso educativo. La magnitud tiene un pequeño problema y es que hacer una raiz cuadrada es algo costoso a nivel computacional. Por eso habitualmente se usa el valor antes de pasar por la raiz cuadrada. Seguirás teniendo un valor que representa la distancia pero será más eficiente. Podemos crear esta implementación de la siguiente forma y equivale al SqrMagnitud de la clase Vector: Esto es genial, tenemos al personaje moviéndose al target y conocemos su distancia hasta él. Pero no queremos que el player avance directamente hacia el objetivo, sino que lo haga poco a poco a la velocidad que nosotros queramos. Para esto vamos a necesitar normalizar nuestro vector. Normalización Normalizar un vector es cambiar su longitud a 1, manteniendo su dirección. En nuestro caso de ejemplo, el vector “dir” que tenemos. Al cambiar su longitud a 1 podemos controlar la velocidad de movimiento mediante un valor multiplicador. ¿Cómo calculamos el vector normalizado (no confundir con el Vector normal)? Dividiendo el vector por su magnitud: Podemos implementar rápidamente esto en nuestra clase BasicMath: Podemos ver que equivale al valor normalized de la clase Vector: Una vez tenemos el valor normalizado, podemos multiplicarlo por un valor y hacer que el personaje se mueva en función del tiempo: Vamos a tener que pasar nuestra normalización a Vector3 ya que estamos trabajando en dos dimensiones y la posición añade la Z (aunque como este caso sea 0). Si modificamos el valor speed podremos hacer que el personaje cambie su velocidad al moverse a través del vector. Antes de continuar me gustaría darte otra forma de mover un vector de un punto a otro. Pero en lugar de basado en la velocidad, basado en un valor comprendido entre 0 y 1. Cuando el personaje está en su posición inicial, el valor es 0 y cuando llega a su objetivo es 1. Esto es llamado interpolación (Lerp). Interpolación Para interpolar un vector simplemente vamos a sumarle al vector inicial, el vector de dirección al objetivo por un valor t (comprendido en 0 y 1). Veámoslo en código: La primera línea limita la t entre 0 y 1. La segunda simplemente suma al vector de origen, el vector dirección multiplicado por t. Si la t es cero devolverá el valor “a” y si es 1 devolverá el valor “b”. Con el siguiente código podremos probar esta funcionalidad nueva: Tenemos que crear un valor t (el atributo Range nos ayudará a limitarlo entre 0 y 1) y un Vector3 que guarde la posición inicial. Esto es necesario porque si le pasamos la posición actual al Lerp los resultados se irán actualizando al ir moviéndose y el resultado no será el que buscamos. Comentamos la anterior MoveToTarget y añadimos la nueva en la función Update. De esta forma si pulsamos Play tendremos un valor t en el inspector que si vamos moviendo entre 0 y 1 hará que nuestro player se desplace más o menos cerca del target. Hay otros tipos de interpolación que veremos en el apartado de Funciones en próximas partes de este tutorial. Una vez tenemos esto, vamos a pasar con una de las operaciones con vectores más importante. Producto Escalar El producto escalar (dot) es una operación entre dos vectores que nos devuelve un valor. Este valor nos da información muy útil sobre estos dos vectores: Si este valor es cero: el ángulo entre los dos vectores es 90 grados por lo que son totalmente perpendiculares. Si este valor es negativo: el ángulo es mayor a 90 grados. Cuanto menor sea este valor, mayor será el ángulo. Si este valor es positivo: el ángulo es menor que 90 grados. Cuanto mayor sea este valor menor será el ángulo. Aquí puedes experimentar visualmente con estos conceptos: https://www.fisicalab.com/apartado/producto-escalar La fórmula del producto escalar, siendo “a” y “b” dos vectores, es la siguiente: dot = ax * bx + ay * by Ya conocido el concepto vamos a practicar con él. Primero lo añadimos la función a nuestro BasicMath. Ahora añadimos la función Dot de testeo con lo siguiente: Esto calculará el producto escalar entre el vector del personaje y el vector de dirección. Como ves hemos utilizado el transform.up en lugar de la posición. Este valor indica la dirección del vector hacia arriba teniendo como referencia el tranform. Ya conocerás estos vectores si estás habituado a trabajar con Unity. Podemos verlos mejor aquí: Si usamos estos vectores a la hora de calcular el producto escalar, los resultados serán en función a la dirección y no en función de la posición. El vector de posición no nos indica hacia donde está apuntando, sino su posición con respecto al centro del mundo. Una posición por ejemplo de (3,4,0) no nos es útil para calcular el producto escalar, sin embargo el vector.up (0,1,0) sí, ya que es una dirección en este caso hacia arriba. También hemos normalizado los dos vectores antes del dot para que sea más fácil trabajar con el resultado. Activamos esta función en Update, comentando lo demás (puedes dejar el MoveToTarget si quieres). Si damos Play podemos ir moviendo el target y ver como va cambiando el producto escalar. Pero ¿de qué sirve conocer este valor?. Pues anteriormente vimos que este valor nos da información muy relacionada con los ángulos. De hecho podemos calcular el ángulo entre dos vectores conociendo los productos escalares. Ángulo Para calcular el ángulo tenemos la siguiente fórmula,siendo “a” y “b” vectores: θ = arcocoseno (dot(a, b)) Vamos a añadir esto a nuestro BasicMath. Este resultado estará en radianes por lo que crearemos dos funciones, una en radianes y otra que convierta el resultado a grados. Hemos normalizado ambos vectores antes de hacer el Dot. De esta forma lo hará desde dentro y podremos pasarle el vector sin normalizar. El valor Rad2Deg es el factor de conversión de radianes a grados que es 180 . Esto es un valor constante: No es necesario que añadas tanta precisión, puedes coger los decimales que quieras para este fin. Creamos ahora nuestra función Angle en el Player (puedes sustituir la función Dot ya que no la volveremos a usar). Volvemos a usar el Vector.up y añadimos la función al Update para verla. Para visualizar mejor el ángulo, voy a añadir en el OnDrawGizmos el siguiente código. Esto crea dos líneas que simular el comportamiento de los vectores. Si damos al play podremos ver dos líneas que forman un triangulo, el angulo entre las dos es el que nos está mostrando por consola: Con este valor de ángulos podrías, por ejemplo, rotar al personaje para que siempre mire al target con la función transform.Rotate. Con esto llegamos al final de esta entrada sobre vectores. Ha sido algo básico pero que sirve como punto de partida si quieres profundizar por ti mismo. Como he comentado estos cálculos son teniendo en cuenta solo 2 dimensiones. Te animo a que realices los cálculos añadiendo a las fórmulas una dimensión más. Podéis encontrar el código del proyecto aquí Recuerdo que no soy matemático y que los cálculos que aquí he realizado pueden contener errores o no ser del todo precisos. Cualquier duda o anotación siéntete libre de contactar conmigo. Nos vemos en la siguiente entrada.
  35. 1 point
    Cuando decidí dedicarme a crear videojuegos una de mis preocupaciones principales era mi escaso conocimiento matemático. Internet estaba lleno de mensajes asegurando que no es necesario saber matemáticas para crear videojuegos y aunque, pueda ser cierto en determinados casos, creo que aprender las nociones básicas te van a ayudar a saber lo que estás haciendo y sobre todo a construir mejores juegos. Como veréis no es necesario un conocimiento matemático avanzado para entender gran parte de los cálculos habituales. En esta serie de publicaciones voy a hablaros de algunos conceptos matemáticos básicos que se usan constantemente en videojuegos: Trigonometría Vectores Matrices Funciones Trigonometría La trigonometría, como su nombre indica (tri-tres; gono-ángulo; metría: medida), es la ciencia destinada al estudio de las medidas de los ángulos. Si por ejemplo quieres girar un personaje en tu juego necesitarás un ángulo de giro. Para poder medir un ángulo (o cualquier cosa en general) necesitamos una unidad de medida, vamos a ver las dos principales en el caso de los ángulos: Grado Cuando vas a comerte una pizza lo primero que haces (después de cocinarla claro) es partirla en diferentes trozos. Imagina que la cortamos en 8 trozos, siempre en 8 trozos porque nos encanta el tamaño de cada trozo. Si quisieras medir el ángulo de cada trozo podrías crear tu propia unidad de medida basada en tu especial devoción por los 8 trozos. Llamémosle pizzo a esta medida. Entonces si tu cortas tu pizza en 8 trozos, cada trozo tendría un ángulo de 1 pizzo. Podríamos pedir que se estableciera como medida oficial el pizzo pero me temo que ya tenemos una medida general que puedes usar en su lugar: el grado. Si en lugar de 8 trozos partimos la pizza en 4 trozos iguales y establecemos que cada trozo vale 90 grados, tendríamos la definición de grado. La definición es la siguiente: cada una de las partes que resultan en dividir en noventa partes un ángulo recto. Aquí podemos recordar los tipos de ángulos rápidamente. Radián Una vez hemos recordado la unidad familiar que es el grado, vamos a ver el radián que es el que usaremos de forma habitual. Pero antes de entrar en el radián, debemos conocer el número Pi. ¿Qué es Pi? El número Pi es uno de los más importante en las matemáticas. Su definición es la siguiente: Pi es la relación entre la longitud de una circunferencia y su diámetro. Pero ¿qué significa esto? Pues básicamente quiere decir que sí dibujamos una circunferencia de diámetro 1 y medimos su longitud, obtenemos Pi. Con esta imagen lo entenderás mucho mejor. Si pintamos el borde de una rueda de diámetro 1 y giramos mientras pintamos el suelo midiendo la longitud de la mancha de pintura, tenemos Pi, que es un valor constante (e infinito): 3.14159… De forma habitual se trabaja con radio = 1 en lugar de diámetro = 1. Por lo que la longitud de la circunferencia es este caso sería el doble de Pi (2 π). Como apunte este número es conocido como Tau y su valor es 6.28318… Pero, ¿qué relación tiene esto con un radián? Si seguimos con el ejemplo de la pizza anterior, imagina que te ha venido la inspiración y has cortado la pizza de tal forma que la longitud del arco de cada trozo que has partido mide exactamente 1. Vamos a verlo gráficamente: La pizza tiene radio = 1 y cortamos (no tendrías que cortarla realmente porque es minúscula pero bueno) un trozo cuya longitud de arco es exactamente 1 (arco azul en la imagen). Pues bien, el ángulo que se forma, nombrado “a” en la imagen, mediría exactamente 1 radián. ¿Que pasa si seguimos cortando trozos con longitud de arco 1? Pues tenemos que el ángulo que se forma con media circunferencia (“a” en la imagen) es π radianes. Y el de la la circunferencia completa sería 2π (Tau) radianes. Nota: los dibujos son solo explicativos, las distancias dibujadas no usan medidas reales. Seno, Coseno y Tangente Una vez conocemos el concepto de radián vamos a experimentar un poco con las circunferencias. ¿Qué pasaría si formamos un cuadrado cortando el eje x e y de la siguiente forma? ¿Como calculamos el valor de “x” y de “y”? ¿Que son x e y? Pues aunque resulte sorprendente esos valores son el seno y el coseno del ángulo “a”: La definición nos dice que el coseno de "a" es la abscisa de su punto asociado y el seno de a es la ordenada de dicho punto. Creo que es mucho más entendible con la imagen anterior. A medida que el ángulo cambia, sus valores en x e y modifican su valor. Aquí podemos verlo mejor: La tangente como ves es la recta que toca en un solo punto la circunferencia en función del ángulo. Teorema de Pitágoras En este punto vamos a hablar de otro término muy importante en matemáticas y que usaremos en los siguientes publicaciones, el Teorema de Pitágoras. Este teorema dice que dado un triángulo rectángulo, podemos relacionar su hipotenusa(h) con sus lados (x e y) de la siguiente forma: Despejando tendríamos: ¿Pero qué uso tiene esto? Pues en el siguiente episodio hablaremos de su uso con Vectores. Imagina que tienes un personaje en un escenario y quieres saber a cuánta distancia está un determinado enemigo. Deberás plantearlo con el teorema de pitágoras, donde la “h” es la distancia entre tu personaje y el enemigo. Tendrías que calcular la “x” e “y” para posteriormente poder despejar “h”. Pero vamos a verlo con un ejercicio simplificado: Imagina que tenemos el siguiente triángulo. Para calcular h haríamos lo siguiente: ¿Y si quiero conocer el ángulo? Para conocer el ángulo necesitamos profundizar nuestro conocimiento en las razones trigonométricas. Vamos a verlo siguiendo el mismo ejemplo: Para calcular θ vamos a necesitar calcular primero el seno del ángulo. Pero ¿cómo hacemos esto sin conocer el propio ángulo? Anteriormente vimos que: Esto es así siempre y cuando el radio (la hipotenusa) fuera 1. Pero ¿qué pasa si como en este caso la hipotenusa es 7.81? Solo tendremos que dividir la variable entre la hipotenusa de la siguiente forma: Vale ya sabemos calcular el seno sin tener el ángulo: Una vez tenemos el seno necesitamos conocer el concepto de función trigonométrica inversa. No os asustéis porque el concepto es muy simple. Necesitamos algo que multiplicado por el seno (que ya lo conocemos) nos de el ángulo. Veremos más a fondo este término cuando veamos las matrices. En este caso las función trigonométricas inversas las conocemos y son las siguientes: Nota: en español también se les llama cosecante (arco seno), secante (arco coseno) y cotangente (arcotangente) Ya conocemos cómo obtener el ángulo: Ya tenemos el valor en radianes del ángulo. Si necesitamos pasar de radianes a grados, podemos usar las siguientes fórmulas: Aquí podemos ver gráficamente las razones trigonométricas que hemos visto aquí: Espero que os sea de ayuda y perdonad si he cometido algún error o he explicado algo de forma muy torpe. No soy ni mucho menos un experto matemático, mi intención es que todos podáis acercaros y verlas un poco más fácil. Cualquier duda estaré encantado de ayudar. En la próxima parte veremos Vectores y pondremos en práctica todo lo aprendido aquí pero dentro de Unity. Hasta la próxima.
  36. 1 point
    Hola gente les dejo un link a mi curso de youtube, totalmente gratuito y disponible para la comunidad. Esta totalmente actualizado al 2020 y hecho por mi, soy programador con titulo universitario y 10 años de experiencia en unity! El curso esta dividido en niveles de dificultad, Comenzando para gente que nunca toco unity y terminando con contenido muy avanzado como creacion de framework propios para multiplayer, entre otras cosas. Para que los usuarios mas avanzados puedan saltearse las partes que no les sirve y explorar mas fácilmente el contendio. Son mas de 200 videos, con muchisimas horas de grabacion que complete con la intención de subir a udemy. Al terminarlo cambie de parecer y ahora lo estoy subiendo de forma gratuita a youtube. Se sube 1 video cada dia de forma atomatica, y ya estan todos los videos seteados para subirse a youtube de forma automatica a este ritmo. Link: https://www.youtube.com/channel/UCl3p_fKnx2-GIUWVbiDAcMg Sin mas, espero verlos por mi canal y que les sirva el curso. Un saludo!!
  37. 1 point
    Voy a reunir pequeños tips de Unity que se pueden resumir en pocas frases. Esta lista se irá agrandando poco a poco en el futuro. Podéis añadir los vuestros si queréis. La idea es TIP + imagen representativa. Puede usar el atributo MenuItem para agregar menús contextuales que pueden llamar a funciones estáticas. Además, si desea crear teclas de acceso rápido, puede agregar caracteres especiales ("%" para ctrl, "#" para shift, "&" para alt) Recuerde guardar las cadenas repetidas en una variable constante. Verifique que su sistema de partículas tenga un culling automático. Si no tiene,revise las razones o use CullingGroup Puede usar el atributo ContextMenu para probar su código en la ventana del editor No olvide optimizar sus Animators con el modo de selección. Esto deshabilita la animación cuando no son visibles.
  38. 1 point
    En esta entrada vamos a aprender a crear nuestro primer shader Vertex/Fragment en Unity. Iremos paso a paso hasta terminar creando nuestra propia bandera con ondulación: Requisitos Para crear este proyecto podemos usar cualquier versión de Unity 2018/2019/2020 siempre y cuando a la hora de crear el proyecto usemos la plantilla de 3D (Built-in Render Pipeline) Antes de pasar al código, creo que es necesario que definamos qué es un shader y las partes que lo componen. ¿Que es un Shader? Un shader es un contenedor de instrucciones que se envían a la GPU para mostrar los elementos que tenemos en pantalla. Al igual que el script de un personaje contiene las instrucciones para que este se mueva o gire, el shader contiene información sobre el color o los vértices de un objeto. Al igual que para escribir comportamientos Unity usa C#, para escribir shaders Unity usa su lenguaje llamado Shaderlab. A su vez Shaderlab permite escribir fragmentos de código en CG (C for Graphics) que es donde realmente estará el código del shader en sí. El lenguaje CG fue desarrollado por Nvidia y Microsoft y es compatible tanto con OpenGL como con DirectX. Veremos más adelante en profundidad las partes que componen Shaderlab y CG. Tipos de Shaders En Unity tenemos dos opciones a la hora de crear un shader. Surface shaders: podemos definirlo como una "plantilla" creada por Unity para facilitarnos gran parte del trabajo aunque dando menos control sobre el resultado final. Vertex/Fragment shaders: el código que existe bajo la capa de Surface anterior. Tiene mayor complejidad pero ofrece mayor control sobre el resultado. En esta entrada nos centraremos en estos últimos, ya que el paso a Surface (o a ShaderGraph) es mucho más productiva si conocemos los conceptos del Vertex/Fragment. Fases del Pipeline Para conseguir mostrar un objeto de juego (3D) por pantalla (2D) se requiere de un proceso con varias fases. Ese proceso es llamado Rendering Pipeline. Para que sea más sencillo de entender, voy a resumir los pasos para centrarnos en los que nos interesa ahora. Básicamente tenemos dos funciones que podemos modificar: Vertex: En esta función podemos modificar datos relativos al mesh, principalmente la posición de los vértices, de ahí su nombre. Consta de una entrada de datos (como la posición de los vértices mencionada o las uvs) y produce una salida que será el input de la función fragment. Fragment: En esta función obtenemos los datos recibidos después de convertir las coordenadas del objeto en coordenadas de pantalla. Por ello todas las modificaciones aquí son a nivel de coordenadas de pantalla. Por ejemplo el color, su transparencia etc. Esta explicación es muy superficial y muy rápida, puedes encontrar más información aquí: https://en.wikipedia.org/wiki/Graphics_pipeline Una vez explicado esto, vamos a pasar a la parte práctica. Abrimos por fin Unity y creamos el proyecto con la plantilla de 3D que comentamos (Built-in Render Pipeline). Partes de un Shader en Unity Para empezar vamos a crear una nueva escena. La abrimos y creamos un nuevo Shader Unlit: Le ponemos de nombre FlagEffect por ejemplo y creamos un Material que lo use. Ahora crearemos un cubo en la escena y le colocamos las siguiente posición, rotación y escala: Creamos ahora un Plano, le arrastramos nuestro material y lo colocamos en: Si todo ha ido bien deberás tener algo así. Puedes ajustarlo tú a tu gusto (aunque ten cuidado al girarlo ya que podrías no tener el resultado esperado al final) Una vez creada nuestra bandera, vamos a abrir el shader FlagEffect. Vamos a borrar todo el contenido y vamos a ir conociendo sus partes poco a poco. Esta sería la estructura del shader con la que deberías empezar: Shader: La carpeta donde se registrará nuestro shader. Properties: Son las variables que podemos crear y ver a través del inspector del material. Cuando en un inspector ves una cajita para la textura, un botón para el color o un campo con un valor numérico aquí es donde se deben crear. La sintaxis es la siguiente: NombreVar ("TextoInspector",TipoVariable) = ValorPorDefecto Aquí podemos ver las diferentes propiedades que podemos crear en Unity: https://docs.unity3d.com/Manual/SL-Properties.html SubShader: El contenido del shader estará aquí dentro. Pass: Cada llamada de pintado que haremos. Cada una tendrá sus funciones Vertex y Fragment. Por defecto solo tendremos y necesitaremos una. Aquí es donde estará el código, acotado entre la pauta de inicio y de fin de CG que vemos en la imagen. Fallback: no es obligatorio aunque es recomendable. Si nuestro shader no es compatible con la plataforma en la que corra, se llamará a otro shader para evitar que se vea rosa. Pero para nuestras pruebas recomiendo borrar la línea. De esta forma si tenemos algún problema con nuestro shader podremos verlo directamente (de otra forma puede que llame al Fallback y no lo veamos rosa). Una vez tenemos la plantilla básica, vamos a añadir las funciones de Vertex y Fragment y los input/output necesarios. Vamos a empezar creando estos últimos. Como vimos anteriormente vamos a necesitar una entrada a la función Vertex y una salida de ella. También necesitamos una salida de la función fragment. Para esto usaremos struct de C (que se declaran igual que en C#). Ahora vamos a necesitar las funciones Vertex y Fragment. La primera tendrá como parámetro su input y devolverá el output. La Fragment tendrá como parámetro el output del vertex. Hasta aquí simplemente tenemos las funciones creadas con sus correspondientes inputs/ouputs configurados (aunque vacíos). Si vamos a Unity veremos nuestro material rosa y eso es debido a que el shader cree que nuestras funciones son diferentes a las Vertex/Fragment. Tenemos que decirle mediante un #pragma que la función de vertex se llama vert en nuestro código y que la función fragment se llama frag. Puedes ponerle otro nombre a las funciones sin problema, siempre que en esta conexión lo pongas bien: De esta forma ya no tendremos problemas con nuestro shader, salvo por el pequeño problema de que no se ve nada. Inputs y Outputs En este apartado vamos a rellenar nuestros structs de datos con la información que necesitamos en nuestras funciones de vert y frag. Dependiendo del shader que estemos creando vamos a necesitar más o menos datos dentro de los inputs. Por ejemplo si solamente queremos cambiar el color del objeto a rojo, no necesitamos datos de UV. Podemos ver todos los datos que podemos usar en cada función aquí: https://docs.unity3d.com/Manual/SL-VertexProgramInputs.html En nuestro caso vamos a necesitar para las ondulaciones de la bandera, la posición de los vértices y las coordenadas de uv del modelo. Para ello vamos a crear estas dos variables dentro de vertexInput y de vertexOutput. Lo que aparece después de los dos puntos es la semántica y es necesario para conectar los datos. En el artículo anterior de Unity explica esto más detenidamente* * Te darás cuenta de que Unity en el output usa SV_Position, que simplemente es un valor de sistema que lo hace más compatible con los sistemas actuales, para facilitar el entendimiento lo he obviado y he usado el POSITION Llegados a este punto voy a explicar rápidamente los tipos de variables que podemos usar dentro de CG. Como ves he usado fixed2 y fixed4. El número al final hace referencia a vectores de 2 y 4 datos. Sería algo similar a un Vector2 o un Vector4. El tipo fixed es el tipo de menos coste y de menor precisión. Estarás acostumbrado a ver float o int. Estos también pueden ser usados de la misma forma que fixed. Aquí puedes ver los tipos de datos: https://docs.unity3d.com/Manual/SL-DataTypesAndPrecision.html También puedes crear matrices siguiendo la misma lógica, la sintaxis sería “float4x4”,siendo los valores del final las filas y las columnas. Una vez tenemos el vertex con los datos, vamos a pasar al fragment. Este simplemente necesitará un valor, el color final del pixel. En este caso usaremos SV_Target que es el que Unity recomienda por defecto. Como he dicho tienes más información acerca de la semántica en los enlaces anteriores. Como normalmente el fragment solo tiene un valor de devolución, puedes optimizar y borrar el struct de output cambiando el frag de la siguiente manera. El resultado es el mismo que el anterior pero en menos pasos. Ahora vamos a rellenar nuestra función de vertex. Pero antes vamos a necesitar incluir funciones que Unity nos ofrece para facilitarnos el trabajo. Como hemos dicho antes, vamos a convertir la posicion 3D del objeto en posición de pantalla. Para esto vamos a usar una función de Unity llamada UnityObjectToClipPos. Esta función recibe la posición de los vértices y devuelve las posiciones en espacio de pantalla para después usarlas en la función fragment. Para poder usarla vamos a incluir esta línea debajo de los #pragma. El #include sigue la misma lógica que los using en C#, de esta forma podemos hacer uso de funciones que Unity tiene preparadas (como la que hemos comentado antes). Ahora en la función vertex vamos a igualar el output que devolveremos a lo que la función UnityObjectToClipPos nos devuelva. De esta forma convertiremos los vértices para el fragment. También vamos a igualar de momento las uv del input y del output, aunque las usaremos justo ahora. Procedemos ahora a mover por fin los vértices. Para esto vamos a necesitar conocer por un lado la variable interna _Time que posee Unity, similar a Time.deltaTime. Esta es un Vector4 con diferentes tipos de tiempo en cada una. Aquí podemos ver más información de esa y de otras variables internas de Unity: Por otro lado vamos a hacer uso de la función seno de CG para las ondulaciones. Creamos una nueva función en nuestro shader, de nombre flag que devuelva un fixed4. Además tendrá como parámetros la vertexPosition y las uv. Tened en cuenta que el shader compila de arriba hacia abajo, asique si escribís vuestra función al final y la usáis antes, dará error. Siempre tenéis que crear vuestras funciones antes de usarlas (a diferencia de C# por ejemplo). ahora dentro vamos a ir sumando a la vertexPosition el seno de _Time.y (el tiempo por defecto).Lo igualamos en la función vert al o.vertex quedando así: Estamos simplemente moviendo los vértices del input y asignándoles al output. Posteriormente convertimos con el UnityObjectToClipPos y seteamos las uv del input al output. Si probamos el efecto, vemos el movimiento pero no es lo que queremos. Esto es debido a que el seno en Time es constante por lo que siempre se mueve de forma uniforme. Vamos a añadir el valor de uv.x (valor de 0 a 1) y restarle el Time para conseguir el efecto que queremos. De esta forma funciona, pero vamos a necesitar ajustarlo. Para esto vamos a crear tres propiedades de tipo Range. Esto es similar al atributo Range de Unity para los valores numéricos en C#. Te permite mostrar un float en el inspector del material y moverlo con un slider entre dos valores. Ahora podrás ver las tres variables en el editor. Pero para poder usarlas tenemos que declararlas en CG con el mismo nombre que tengan en la propiedad (_Speed,_Frecuency, _Amplitude). Usaremos el tipo fixed. Estas variables las vamos a usar de la siguiente forma: Speed: va a multiplicar al _Time.y para acelerar y reducir la velocidad. Frecuency: va a multiplicar a la resta entre uv.x y la multiplicación del Time y la speed. Justo antes de hacer el seno. Amplitude: multiplica al valor una vez el seno se ha calculado. Estos son los tres cálculos básicos a la hora de modificar la ondulación. Grábalos en tu mente (o apuntalo mejor) porque los usarás muchas más veces en tu vida. Si todo ha ido bien, podrás ajustar los valores como quieras para mejorar la ondulación. Aquí puedes ver mi configuración: Solo nos quedan dos pasos para terminar. El primero es hacer que la bandera se pegue al poste y no ondule. Esto es muy fácil de conseguir teniendo las referencias de uv.x que, como dijimos van de 0 a 1. Solo tenemos que multiplicar el seno que tenemos por la uv.x. De esta forma anclamos la bandera, consiguiendo que la ondulación vaya de mayor a menor fuerza desde el poste (gracias al valor entre 0 y 1 de uv.x) Lo otro que nos queda es añadirle color. Aquí voy a poner dos opciones, la primera es la básica, añadir un color sin más. Si estás cansado y no quieres continuar es la opción que te recomiendo. Podrás volver otro día para ver la segunda opción. En la segunda opción usaré un lerp para darle a la bandera 3 colores diferentes en función de la Y de su UV. Añadir color básico Simplemente tendrás que añadir una propiedad _Color y una variable de CG para conectarla (al igual que la _Speed y los demás valores anteriores). En este caso el color tiene cuatro valores, así que usaremos fixed4. Y en la función frag devolvemos el color a pelo. Añadir color avanzado Si venimos del básico vamos a borrar la propiedad de color (o cambiarle el nombre) y crear otras tres diferentes. Estas se llamarán ColorTop, ColorMiddle, ColorBotton (o el nombre que tu quieras). Estos tres colores serán las tres franjas que tendrá la bandera. Ahora creamos una función nueva encima de frag con el nombre getPixelColor que devolverá un fixed4. Esta función analizará la posición de la uv en Y (la necesita como parámetro) y haciendo uso de la función lerp y step nos devuelve un color u otro. ¿Qué hacen realmente cada una de estas funciones? Puede ser complicado de leer tal y como está, pero solo necesitas saber lo que hace para entenderlo. La función lerp interpola entre dos valores con un valor t. Cuando t es 0 devuelve el primer valor y cuando es 1 devuelve el segundo valor, devolviendo valores intermedios. En nuestro caso no queremos valores intermedios, queremos una interpolación directa dado un valor de referencia. El valor de referencia será ⅓ ya que tenemos 3 franjas. La función step tiene dos parámetros, si el primero es mayor que el segundo, devuelve 1, si es menor devuelve 0. Esto unido al lerp hace que en valores superiores a 0.33 pero inferiores a 0.66 se coloree del color del centro. Y de igual forma en valores superiores e inferiores. Con esto hemos llegado al final de la entrada. Si tienes cualquier duda con esto déjamela en los comentarios. PD: Si queréis que la bandera se muestre en ambas caras, tendréis que cambiar un valor del Cull. Esto es fácil de hacer pero da para otra entrada junto a otros añadidos como el Blend el ZTest o el ZWrite. De momento para que te quede perfecto, solamente tendrás que añadir junto antes del Pass (o dentro del Pass antes de CGPROGRAM) la siguiente linea: Con Cull en Off no ocultará ninguna cara. Nos vemos en la próxima entrada.
  39. 1 point
    Puedes asegurarte de que una variable no es nula añadiendo ‘?’ antes de acceder a ella. Puedes crear strings con variables dentro añadiendo ‘$’ delante y las variables entre corchetes. Puedes sacar un material de un shader concreto creándolo con el shader seleccionado. Puedes cambiar la respuesta de Unity cuando realizas cambios en un script mientras estás en Play. Sólo tienes que ir a Edit/Preferences/General Puedes cambiar la configuración del orden de transparencia desde Project Settings/Graphics. Muy útil para juegos 2D donde quieras controlar el orden de pintado en función de su Y.
×
×
  • Create New...