domingo, 28 de agosto de 2016

Desarrollando un clon de Flappy Bird en Unity3D con Playmaker (Parte 1)

Blosky Dev

En esta ocasión presento un tutorial para aquellos que están comenzando a desarrollar videojuegos utilizando la herramienta Unity, y qué mejor ejemplo que aquél éxito meteórico del 2013: El Flappy Bird. Iré colocando todos los pasos que seguí para crear este minijuego, así que sigue leyendo para aprender cómo se hace un juego de este estilo.

En mi anterior post expliqué un poco acerca de Playmaker, así que si aún no sabes de qué trata te sugiero que leas este post primero (Simplificando el manejo de Unity3D con Playmaker y la Programación Visual). Asimismo, estoy asumiendo que ya tienes instalado el Unity con el Playmaker (versión 1.8.2). Tener esta versión del Playmaker es importante, ya que incorpora nuevas funcionalidades como ser las físicas 2D, trigonometría y otras, que es lo que justamente necesitaremos para programar las mecánicas 2D dentro de este juego.

Otro elemento previo necesario será contar con algunos archivos necesarios del juego. En esta ocasión sólo necesitaremos la hoja de sprites, que está disponible en este enlace: sprites.png

Comencemos. El primer paso es abrir Unity3D, crear un nuevo proyecto 2D, y crear la estructura básica de las carpetas que tendremos en el proyecto, colocando sprites.png en la carpeta Sprites. Nuestro proyecto deberá verse de esta manera:


Una vez hecho esto, el siguiente paso es importar el Playmaker a nuestro proyecto. Una vez importado y recompilado el proyecto, ya estaremos listos para incorporar los primeros elementos a nuestra primera escena.

Dado que todos nuestros elementos visuales se tratan de sprites, no tendremos problemas para ubicarlos. Todos se encuentran en la Sprite Sheet (hoja de sprites) llamada sprites.png, que ya hemos incorporado al proyecto. Esta imagen contiene todos los sprites del juego así como las animaciones, pero se encuentran unidas, por lo que deberemos editarla y separar cada elemento. Para ello Unity nos brinda una herramienta muy útil llamada Sprite Editor, a la cual se accede mediante el botón del mismo nombre, que se encuentra en el Inspector del elemento. Al hacer clic en este botón, se mostrará el Sprite Editor en una nueva ventana, tal y como se ve en esta imagen:


Adentro del Sprite Editor, tenemos una herramienta más útil aún llamada Slice, y cuya función es de seleccionar todos nuestros sprites y cortarlos de forma automática. Lo que hay que tomar en cuenta al usar esta herramienta, es de mantener suficiente espacio vacío entre cada elemento independiente, para que los sprites no queden unidos al final. No tendremos que preocuparnos ahora mismo ya que el archivo ya tiene suficiente espacio entre elementos. Una vez que hayamos realizado el Slice de todos los sprites, cada uno se mostrará como un elemento independiente en la ventana "Proyecto", tal y como se ve a continuación.


Ahora que ya tenemos los sprites del juego separados, podemos comenzar a usarlos individualmente. Tomaremos al personaje principal, como punto de partida. Dado que hay tres diferentes esquemas de color, podemos usar cualquiera de ellos. Yo voy a tomar el de color rojo. Eso quiere decir, que los sprites que tomaré en cuenta son todos los que tengan un ave roja, que en este caso son tres sprites de la hoja de sprites.


¿Y por qué estoy tomando los tres en lugar de uno? De esta forma estoy creando la animación que tendrá el ave durante el juego, la cual está compuesta por estos tres sprites que se irán sucediendo uno tras otros de forma indefinida. Si te fijas, existe una diferencia leve entre cada sprite, y al alternar entre cada uno efectivamente estoy creando una animación de "aleteo", que es la que dará vida a nuestro personaje.

Para finalizar el paso de crear la animación con estos tres sprites (que ahora serán considerados como cuadros o "frames"), simplemente deberemos arrastrarlos a la escena, y Unity se encargará de crear el controlador de animación (Animation Controller) que usará el personaje. Se creará un archivo .anim que guardaremos en la carpeta Animations con el nombre del personaje (yo usé redbird).

Ahora, si nos fijamos en la ventana Animation, veremos que se ha creado una nueva animación con el nombre que hemos colocado. Si queremos hacerla más rápida, modificaremos el valor de "Samples", para que el loop de animación se reproduzca más rápido, tal y como se ve en la imagen a continuación (yo he usado 12 para esta animación).


Para probar que nuestro "Flappy" está funcionando, podemos darle "Play" o reproducir al editor de Unity, y veremos que al comenzar el juego el personaje se mantiene en su posición, pero que está animado al darle play. Si no lo ves por ningún lado al darle play, quizás se deba a que la cámara no le está apuntando directamente, por lo que tendrás que reposicionar la misma para que apunte al personaje.

Una vez concluido este paso, lo siguiente será incorporar el fondo, el suelo, y los tubos a la escena. No será nada complicado, ya que tan solo arrastraremos cada sprite en forma individual. De esta forma, cada uno de estos elementos pasará a ser un GameObject diferente dentro de la escena. Al final, el resultado debería verse más o menos así:


A continuación, lo que haremos es comenzar a utilizar Playmaker para programar los comportamientos de cada uno de los objetos de la escena. Comencemos por el fondo (Background). Hemos decidido de que el fondo aparezca al comenzar el juego, y lo primero que se hará es elegir entre uno de los dos sprites disponibles, por lo que tendremos una primera "máquina de estados" orientada a realizar esta selección. Una máquina de estados, es simplemente un GameObject que posee un componente Playmaker asociado, y que funciona con estados y transiciones, generando diferentes comportamientos a medida que el juego se desarrolla. Creamos la máquina de estados en un nuevo GameObject llamado go_BackgroundSelector, y dentro de este gameobject colocamos ambos sprites (el fondo de día y el fondo de noche). El paso siguiente es deshabilitar ambos fondos para no se vean en pantalla, tal y como se ve en la siguiente figura.


Ahora que el fondo ya está establecido, programaremos el comportamiento para que se muestre uno de los fondos al azar. Esto es posible de lograr en la ventana del editor de Playmaker. Seleccionamos nuestro objecto, nos dirigimos a la ventana del Playmaker, y crearemos la máquina de estados (mediante el clic derecho > agregar FSM). FSM quiere decir Finite State Machine, o máquina de estados finitos. Una vez creada la FSM debería lucir como en la siguiente figura:


Ya que la FSM ha sido creada, y el primer estado (State1) ha sido colocado como el estado por defecto, hacemos clic en el mismo, y a continuación nos vamos a la parte derecha de la ventana del Playmaker, en donde hay cuatro pestañas: FSM, State, Events y Variables. A continuación explico que contiene cada una:

FSM: Lista las FSM que contiene el GameObject en cuestión, y brinda la opción de renombrarlos, ponerles descripción, y una URL, entre otras cosas. Normalmente no es muy utilizada ya que las FSM no serán renombradas en la mayoría de los casos.

State: Estado, esta es la pestaña principal del estado seleccionado, ya que aquí veremos todas las acciones que se realizarán mientras el estado que seleccionamos se encuentre activo. Como en este momento estamos en State1, las acciones que ocurrirán en este estado aparecerán aqui. Podemos agregar nuevas acciones con el botón de la esquina que dice "Action Browser" (Nota: si no te sale el boton o esta pestaña esta vacía es porque no has seleccionado un estado primero. Selecciona el State1 de la izquierda y el botón aparecerá para poder agregar nuevas acciones)

Events: Esta es la pestaña en donde se agregarán las transiciones entre estados, por el momento la dejaremos vacía. En el momento en que vayamos a crear más estados esta ventana será utilizada para definir los nombres de las transiciones de estado.

Variables: Esta es una pestaña en donde iremos creando las variables que utilizaremos en los estados de una FSM. Hay dos tipos de variables: Locales, que serán propias de una FSM, y Globales, que se utilizarán en todas las FSM de nuestro proyecto.

Bueno, luego de vistas cada una de las pestañas volvemos a la pestaña de State, y le damos al botón de "Action Browser" para abrir una nueva ventana con todas las acciones disponibles que Playmaker nos ofrece. Dado que queremos mostrar un fondo o background de un total de dos disponibles lo mejor es crear primero una lista de los fondos, y posteriormente seleccionar uno de ellos al azar y mostrarlo. Entonces eso es lo que haremos. Mediante el filtro buscador de la parte superior escribimos "Array Get Random", y lo seleccionamos tal y como muestra la figura. Haciendo doble clic o Enter en el teclado lo agregaremos a la lista de acciones del State1.


Veremos que la acción se ha agregado al State1, y a continuación podemos cerrar la ventana del Action Browser. Una vez que hemos agregado la acción, faltará solamente el colocarle los parámetros correspondientes. En este caso esta acción tiene 3 parámetros: Array, Store Value, y Every frame. Veamos cada uno de ellos.

Array: Este parámetro necesita ser llenado con un Array, tal como indica su nombre. Un Array o arreglo en español, es una lista de elementos, que puede ser llenada con elementos del mismo tipo. La ventaja que ofrece es que podemos acceder a cualquiera de los objetos de la lista, tan solo referenciando al nombre de la lista, y la posición (no te olvides que en este caso es al azar, ya que la acción que seleccionamos previamente es Array Get Random, o lo que es lo mismo, Obtener Al Azar de la Lista).

Pero el caso es que todavía no hemos creado la lista, y eso es lo que vamos a hacer a continuación. En la cuarta pestaña del Playmaker, tenemos las Variables, y es ahí donde crearemos nuestro Array con los fondos del juego. Nos vamos a la parte inferior, en donde dice "Create New Variable" o Crear Nueva Variable, y crearemos una con los siguientes datos:

Nombre: Backgrounds
Type: Array

Y a continuación le damos al botón "add", para que nuestro Array local llamado Backgrounds aparezca en la lista. Pero ojo, no hemos terminado. Aún no le hemos dicho que tipo de elementos vamos a tener en la lista, por lo que a continuación seleccionamos el array en la lista de arriba, y le cambiamos la propiedad "Array Type" a GameObjects tal y como se ve en la figura a continuación:


Ya hemos definido el array, le cambiamos el tipo de elementos a gameobjects, y sólo nos queda un pequeño paso: añadir los gameobjects en cuestión a nuestro array. Para ello, dimensionaremos nuestro array a un tamaño de 2 (mediante el parámetro Size), y luego arrastramos los dos fondos que están en la ventana de jerarquía del proyecto hacia los espacios del array, tal y como se mostró en la figura anterior.

De esta forma, ya hemos completado la definición del array Backgrounds de tipo gameobjects con sus dos elementos: Background y Background2 (fondo de dia y de noche).

Volviendo a la pestaña State, ya podemos colocar el primer parámetro de la acción Get Array Random, y le colocamos el array Backgrounds, tal y como se muestra en la figura:


Para el segundo parámetro, Store Value, debemos crear una nueva variable del tipo de elemento que contiene  nuestro array, es decir de tipo GameObject. Entonces nos vamos de vuelta a la cuarta pestaña y allí creamos una nueva variable llamada BackgroundSelected, de tipo GameObject, tal y como se ve en la figura:


Una vez creada esta nueva variable, no le vamos a dar valores de inicio como al array, simplemente la dejaremos tal como está, y volvemos a la pestaña de State. En nuestra acción, seleccionamos en el segundo parámetro nuestra nueva variable BackgroundSelected, y así completamos el llenado de esta segunda posición.

El tercer parámetro, Every Frame, no será usado en esta ocasión, por lo que lo dejaremos en vacío.

Eso es todo! Ya hemos terminado de crear la primera acción que irá en nuestro primer estado, en nuestra primera FSM. Esta acción lo que hace es tomar el array que creamos, seleccionar un elemento al azar, y a continuación lo colocará en la variable BackgroundSelected. De este modo hemos seleccionado uno de los fondos, y el siguiente paso será crear una nueva acción para activarlo.

Seguimos en la pestaña dos, y a continuación damos clic otra vez en el botón "Action Browser" para seleccionar otra acción que será la que active este objeto que hemos seleccionado con la acción previa. Buscamos la acción llamada "Activate Game Object" y la agregamos al State1. Si observas con cuidado, verás que se agrega a continuación de la acción anterior, y se ejecutará de igual forma a continuación. Esto es lo que queremos, queremos que esta segunda acción se lleve a cabo luego de haberse ejecutado la primera acción, y no antes. Ambas acciones quedarán listadas de la siguiente manera:


En esta segunda acción, tenemos 5 parámetros:

GameObject: El GameObject al que afectaremos activándolo o desactivándolo.
Activate: El valor de activado o desactivado (esta acción puede realizar el uno o el otro).
Recursive: Quiere decir si afectará a los GameObjects hijos en la jerarquía, o si es que no lo hará.
Reset on exit: Si esta acción volverá a sus parámetros iniciales al finalizar.
Every Frame: Si esta acción se realizará en cada cuadro (frame) durante la ejecución, por el momento no será necesario utilizarla ni cambiarla.

De las 5, por ahora solo cambiaremos la primera, que es GameObject. Necesitamos colocarle un GameObject para que sea activado, y en este caso ya contamos con uno, que viene de la acción anterior: BackgroundSelected. Si recuerdas, la acción anterior seleccionaba un GameObject al azar de una lista, y lo guardaba en una variable. Esta variable se utilizará ahora, ya que es la que queremos que se active en el juego mostrando uno de los dos fondos. Entonces la seleccionaremos en el primer parámetro.

Si has completado todos los pasos con éxito, el juego debería lucir más o menos como en esta última captura al reproducirse:


¡Y eso es todo por ahora! en resumen, hemos creado un GameObject que contiene nuestra primera FSM, hemos configurado el primer estado (State1), y le hemos dado algunas acciones que cumplir o ejecutar utilizando un Array y una variable de tipo GameObject para almacenar los datos. Hemos programado el comportamiento que hace que al iniciar el juego el fondo se cambie por uno de los fondos disponibles al azar. Y de esta manera comenzamos el manejo de Playmaker, una sencilla y potente herramienta de programación visual en Unity3D.

A medida que avancemos en el manejo de Unity, el uso de Playmaker será más sencillo, pero por ahora lo dejaremos en este punto, para seguir avanzando con este tutorial en una nueva oportunidad. No olvides dejar tus comentarios, y gracias por leerme. Sé que quizás no fui muy claro con algunos conceptos, pero te invito también a descubrir por tu cuenta aquellos detalles que he podido pasar por alto. Si es necesario, lee nuevamente cada paso para ver si no te has olvidado de algún detalle. Y si definitivamente no lo logras, escríbeme para que te lo explique nuevamente.

Keep moving! La práctica hace al maestro.

Blosky Dev