viernes, 23 de julio de 2010

Aventuras con Unity – Encontrando el camino...

Pues continuando con la tesis...

Como había comentado anteriormente, el objetivo a lograr es que los personajes salgan de una base y se dirijan hacia otra base, pero hay varias cosas que hay que tener en cuenta, por ejemplo:

  • La posición de las bases varía.
  • Hay obstáculos en el camino.
  • Los personajes deben salir en filas de 4
  • Todos los personajes de la misma fila deben llegar a la base destino al mismo tiempo
  • Los personajes no deben de chocar con otros personajes que estén transitando.
  • Los personajes deben de evitar el chocar con otras bases que estén en el camino.
  • Los personajes deben evitar el chocar con los obstáculos que encuentren en el camino.

Como pueden ver hay que tener en cuenta varias cosas y con los intentos hasta ahora hechos solamente he logrado el punto 1, 3 y 5, así que todavía falta un muy buen tramo para lograr tener el traslado de los personajes por el mundo a punto, entonces manos a la obra.

A fin de lograr que los personajes no colisionen ni con los obstáculos ni con las bases pude ver dos opciones:

1.Aplicar una fuerza constante al personaje y hacer las bases redondas a fin de que cuando se encuentre alguna pues llegue el momento en el que lo salve de forma automática.
2.Implementar un algoritmo de busqueda de camino y aplicarlo a cada personaje para que pueda evadir obstaculos y bases.

La primer opción es bastante mala ya que solo funciona con las bases, no funciona con los obstáculos, además de que los personajes pueden trabarse o perderse y nunca llegar al destino, así que solo sirve como prueba. Pueden ver a lo que me refiero en el Tercer Intento, si se fijan en la luneta de la mitad es redonda y esto permite que los personajes de alguna forma puedan evadirlo, pero deben de chocar con la base para lograrlo.

Debido al éxito no encontrado con la opción 1 tuve q pensar en otra solución y Victor me ayudó comentándome que ya existen implementaciones de algoritmos d búsqueda de caminos y me mandó un link con la implementación del algoritmo A*(A estrella o A star) en Unity.

Para los que no sepan ni que onda con ese algoritmo de forma rápida y sencilla les explico, es un algoritmo que recibe un punto de inicio y un punto final, los cuales tenemos nosotros, y tiene la forma de caminar un paso y saber cuanto le costó caminarlo, de tal forma que comienza a dar pasos siguiendo cierto camino, si ese camino no llega al punto final entonces da un paso hacia atrás e intenta caminar por otro lado, de tal forma que intenta dar pasos por cualquier camino disponible y una vez que llega al punto final sabe cuanto le costó el llegar al final.

Este algoritmo nos garantiza que si existe un camino del punto A al B lo va a encontrar y si quieres, puede calcular el camino óptimo, es decir, el camino que cueste menos caminar.

Aquí esta la definición en la Wikipedia A - Estrella
Aquí esta un ejemplo visual de la implementación del algoritmo en la resolución de un juego A - Extrella

Una vez explicado lo anterior, pues ahora si que me dí a la tarea de bajar la implementación de esta liga: A - Pathfinding

Ya teniendo la última versión pues pasé a realizar el proyecto de ejemplo el cual es bien básico, se trata de un plano de 50mt cuadrados sobre el cual se calcula una malla, donde cada intersección se considera un nodo y el algoritmo A* calcula el camino óptimo siguiendo los nodos para llegar del nodo A al B. Bueno, quizas es un poco mas omplicado que eso, sin embargo me permite ver buenos resultados rápidamente, aquí les dejo la implementación del proyecto básico utilizando la implementación de Aron Granberg:

Astar 1


Para hacer que camine hay que darle click en alguna parte del terreno.
El click no debe ser encima de un obstáculo.
Pueden dar otro click antes de que llegue al destino y se calculará el nuevo camino a partir del punto en donde se encuentra el personaje.

Bueno, hasta aquí le dejaré por lo pronto, es emocionante ver resultados con esta implementación, afortunadamente puedo usarlo en proyectos no comerciales y logicamente tendré que adaptarlo a mis necesidades, pero ya es un gran avance.

Epero sus comentarios, sugerencias y demás, por lo pronto nos seguimos leyendo...

martes, 20 de julio de 2010

Aventuras con Unity 3D - Cubos y colisiones

Siguiendo con el tema de la tésis...

Unity permite agregarle a un GameObject un cuerpo rígido, esto como me beneficia?, pues que el cuerpo rígido puede colisionar con otros objetos rígidos, y se le pueden aplicar fuerzas, como la gravedad, golpes, peso etc.

De esta forma Unity puede hacer los cálculos necesarios para saber como debería de comportarse un cubo si se deja caer desde cierta altura con cierto ángulo. Tembien Unity permite ponerle restricciones, por ejemplo si no quieres que un objeto se mueva en algún eje, pues le dices q no calcule en ese eje y listo, esto es muy útil cuando se hacen juegos en 2D.

Aclarado lo anterior la pregunta que surge es, si le pongo un cuerpo rigido a un objeto, va a interactuar con el terreno, si modifico el terreno para que tenga protuberancias, puede ocurrir que el objeto se atore con esas protuberancias?

La respuesta a la pregunta es que sí, si las protuberancias tienen un ángulo muy pronunciado el objeto no podrá cruzarlas y se atorará, así que ahora resta ver que tan pronunciadas pueden llegar a ser las protuberancias en el terreno para que se desplacen, el resultado tambien lo pueden ver en la liga de la entrada pasada.

Un requerimiento de la tésis es que se van a tener filas de objetos alineadas y avanzarán hacia un objetivo, las condiciones son las siguientes:
Deben de ser sostenidos por el terreno y moverse a la altura de las protuberancias.
No deben de chocar con otros objetos de su mismo tipo.

He aqui el intento que hice para lograrlo: Segundo Intento.

Como se puede apreciar, se logra el primer punto, sin embargo su trayectoria se ve afectada si chocan con otro cubo, es decir, no se cumple el segundo punto.

A fin de lograr que se cumpla el segundo punto tuve que hacer algo de investigación y resultó en éxito, existe un método que lo que hace es que le dice al motor que no calcule las colisiones que puedan ocurrir entre dos objetos, por lo que la tarea ahora fué el agarrar a todos los cubos y mandar llamar esa funcion pasandole como parametro todas las posibles combinaciones de cubos existentes en el mundo. La funcion se llama ignoreCollision.

Sé que suena ineficiente, sin embargo ya dentro del juego no lo es tanto, por que hice una funcion que cuando reciba un cubo llamará a la funcion ignoreCollision para todos los cubos existentes en el mundo hasta ese momento y después lo meterá a ese mismo arreglo.

El resultado puede apreciarse en el Tercer Intento, Por cierto, es dificil apreciar el cambio en este tercer intento, ya que es casi igual que el segundo, pero fijense en el comportamiento de los cubos que inician en la misma fila y verán que esos cubos si chocan entre ellos, pero no chocan contra los cubos de la fila de enfrente, en el tercer intento ya no choca ningún cubo con cualquier otro cubo.

Tercer Intento.

Bueno, espero me halla podido dar a entender, igual si tienen alguna duda o comentario al respecto, por supuesto que es bienvenida, por lo pronto nos seguimos leyendo...

miércoles, 7 de julio de 2010

Aventuras con Unity 3D - Terreno y movimientos

Hace ya unos 15 días que comencé a darle a la estudiada de Unity, como les comenté en la entrada pasada, estoy comenzando desde cero, pero creo q ahi la llevo.

Es realmente fácil el lograr cosas y con los tutoriales que existen puedes lograr cosas q se vean bastante bien, por ejemplo, yo siempre había creado un rectángulo muy delgado y del tamaño que quisiera para usarlo como piso, sin embargo por ahi me encontré un tutorial de como crear un ambiente utilizando un objeto llamado Terreno, las ventajas? puedo darle la forma que quiera, puedo ponerle q tan lejos quiero q se vea el mundo, ponerle neblina, decirle si los montes van a generar sombras, cual va a ser el tamaño máximo de las elevaciones y el mínimo, aplicarle texturas y un largo etc.

Creo q lo complicado es ponerte a jugar con todas las opciones que tienes a fin de lograr algo que te guste, ademas que consume mucho tiempo. Por lo pronto l objetivo era crear un terreno decente, nada espectacular, así que el objetivo se cumplió.

Después me puse a ver lo que se puede hacer con la codificación, Unity t permite crear código en varios lenguajes, el q a mi me interesa es el JavaScript, así que estuve codificando en dicho lenguaje.

Unity permite crear varias cosas, todas ellas quedan como activos del proyecto, los cuales se pueden usar en varias partes, y si le haces un cambio al activo este se actualiza en todos los lugares donde lo hallas usado.

Además, si creaste un objeto y sacas copias de ese objeto, la copia contiene todas las propiedades, activos y comportamientos que tenga el original, vamos solo hace falta diseñar muy bien un objeto y si necesitas muchos mas de esos pues solo necesitas instanciarlos.

Dicho esto, pues me puse a crear un código, solo que a fin de que cualquier código se ejecute debe estar ligado a un objeto que exista en la escena, esto ocurre por que Unity solo le da tiempo de procesador a los objetos que existen en la escena, así que si no lo contiene un objeto, pues no lo corre.

En un tutorial que me encontré viene como hacer que gire un cubo, solo hay que crear un cubo, ponerlo encima del terreno, crear un código que modifique las propiedades del cubo, ligar dicho código al cubo para q sea corrido y correr la escena... Listo, ya tienes un cubo volador que esta girando incansablemente :)

En el ejemplo anterior lo unico q se modifica es la orientación del cubo, pero en el proyecto tendremos que mover a los personajes, así que tuve que lograr que el cubo se mueva en alguna dirección, así que usando el comando de Transform cambio la posición del cubo, solo que hay qu tener en cuenta alunas cosas, como por ejemplo:
  • Normalmente Unity trabaja por frames, es decir, Unity tratará de mostrar la escena X veces en un segundo, normalmente en Web un refrescado de 12-15 frames por segundo es bastante aceptable, sin embargo no todas las personas que acceden a la web tienen el mismo poder de procesamiento, por lo que a algunas personas les va a resultar mas dificil el ver los 15 frames por segundo.
  • Entonces si nos basamos al procesamiento en frames, pues puede que tengamos resultados raros por que un frame se refresca mas o menos veces en un segundo.
  • Para evitar esto lo que se puede hacer es tomar en cuenta el tiempo que ha pasado, sin importar el numero de frame en el que se encuentre el tiempo avanza de forma constante, así que si nos basamos en el tiempo es mas fácil calcular como se debería de ver cierto objeto una vez que ha pasado X tiempo.

Teniendo esto en cuenta entonces lo q hacemos es multiplicar el tiempo q ha transcurrido por la velocidad a la que se desplaza cierto objeto y así podemos calcular la posición que debería de tener el objeto, entonces utilizamos el comando Transform y movemos el objeto a dicha posición y listo, nuestro objeto se mueve!!

Si quieren ver un ejemplo de esto pueden ir a esta liga: Primer Logro

Creo que es suficiente por el día de hoy, les seguiré dando actualizaciones de los avances, los nuevos objetivos y los problemas q me encuentre para lograrlos, y cuando lo logre un pequeño ejemplo de como se ve el logro, por lo pronto nos seguimos leyendo...