Usando el acelerometro como método de entrada para un Juego en Android.

Los juegos que usan el acelerometro no abundan, pero los que lo usan si hacen una buena implementación se convierten en juegos muy especiales.

En el tutorial de desarrollo de juegos para Unity hemos creado un juego que funciona en PC o MAC. Lo vamos a utilizar para explicar como podemos pasar un juego de STANDALONE a Mobile, o mejor aún, veremos como podemos mantener el mismo proyecto para generar los dos ejecutables cambiando tan solo ela plataforma destino en las opciones de Build.

Podéis bajaros el proyecto final del tutorial en este link: megafastball-final.

Como mantener dos plataformas con un mismo código

Hay dos apartados donde podríamos tener diferencias entre una aplicación para PC o MAC y una entre mobil: El código de los scripts y los assets importados, como imágenes o música.

Indicando especificaciones diferentes

En el caso de las imágenes o la música las diferencias se encuentran en la optimización. Para mobil, tienen que ser menos pesados, quizá con menos calidad, en realidad todo lo que podemos para ayudar al mobil a mover nuestro juego sin que vaya muy apurado. Estas optimizaciones se pueden hacer en la sección Inspector de cada uno de los objetos, que nos dará la opción de cambiar las opciones de importación para cada una de las plataformas que tenemos configuradas en nuestro entorno de desarrollo Unity.

Optimizaciones para diferentes plataformas.

En cada fichero que importemos se le puede indicar que opciones queremos usar para cada plataforma. En el recuadro rojo se puede ver que mi entorno de Unity esta configurado para crear aplicaciones standalone (Pc y MAC), Android o Webgl. Si queremos indicar unas optimizaciones diferentes tenemos que marcar el recuadro de Override, y ya podremos trabajar con unas especificaciones diferentes a las generales.

Scripts que funcionen para varias plataformas en Unity

Gran parte de la gestión de la complejidad del desarrollo multiplataforma lo gestiona Unity por si solo, pero aún así, a veces las plataformas son tan diferentes, como puede ser el caso de un PC y un Android, que el código que escribimos no puede ser el mismo. Para este caso Unity nos ofrece los preprocesadores. Es una forma de indicarle que parte del código queremos que se ejecute en cada plataforma.
Algunos de los preprocesadores disponibles para diferenciar las diferentes plataformas són:
UNITY_STANDALONE_WIN
UNITY_STANDALONE_LINUX
UNITY_STANDALONE
UNITY_WII
UNITY_IOS
UNITY_ANDROID
UNITY_PS4
UNITY_SAMSUNGTV
UNITY_XBOXONE
UNITY_TIZEN
UNITY_TVOS
UNITY_WEBGL
La forma de usarlos es muy sencilla, vamos a ver un pequeño ejemplo.

#if UNITY_STANDALONE
Debug.Log("Solo se ejecuta cuando creamos el juego para STANDALONE Unix/Windows/MAC");
#elif UNITY_ANDROID
Debug.Log("Solo se ejecuta cuando creamos el juego para Android");
#else
Debug.Log("Se ejecutara en cualquier otra plataforma");
#endif

Como vemos el uso de la compilación dependiente de plataforma es muy sencillo.

Controles de movimiento por acelerometro.

Partimos de la base de que disponemos de un juego ya creado, que usa la entrada standard de teclado para mover al protagonista, y que lo que queremos hacer es incorporar la posibilidad de moverlo cuando creemos la versión para Android.
Vamos a estudiar nbuestro codigo fuente, el que hemos creado en el tutorial de Unity, y que os podéis bajar de este enlace.

private void Update()
{
// Get the axis and jump input.
float h = CrossPlatformInputManager.GetAxis("Horizontal");
float v = CrossPlatformInputManager.GetAxis("Vertical");
jump = CrossPlatformInputManager.GetButton("Jump");
// calculate move direction
if (cam != null)
{
// calculate camera relative direction to move:
camForward = Vector3.Scale(cam.forward, new Vector3(1, 0, 1)).normalized;
move = (v*camForward + h*cam.right).normalized;
}
else
{
// we use world-relative directions in the case of no main camera
move = (v*Vector3.forward + h*Vector3.right).normalized;
}
}
private void FixedUpdate()
{
// Call the Move function of the ball controller
ball.Move(move, jump);
jump = false;
}

Estas dos funciones forman parte de un script que hemos incorporado en nuestro protagonista, y que se encarga de controlar sus movimientos.

Las dos funciones, Update y FixedUpdate son llamadas por Unity. Entonces, ¿Por que utilizamos las dos funciones? Bueno, la diferencia principal entre Update y FixedUpdate es el momento en el que se produce la llamada. Update se llama en cada cambio, en cada frame, sin tener en cuenta si hay diferencias entre el frame y el framerate, que si se tiene en cuenta para las llamadas a FixedUpdate. Resumiendo, FixedUpdate normalmente se llamara menos veces que Update. Digamos que un juego que corre a 25 fps llamara menos a FixedUpdate que otro que corra a 30fps, pero los dos realizaran el mismo numero de llamads a Update.

En la función Update las tres primeras lineas se encargan de recoger la pulsación del usuario mediante una llamada a las funciones CrossPlatformInputManager. Estas funciones estan incluidas dentro de los Assets standard de Unity y nos devuelven las entradas de teclado o joystick que tengamos conectado. Las teclas que usa las podemos definir desde el menú Edit->Project->Settings->Input.

Menú donde podemos configurar teclas de entrada para Unity.
Parte de la configuración de controles de entrada.

Aunque podemos cambiar las teclas, las que vienen por defecto son las conocidas por la mayoría de los jugadores.
Después de capturar las teclas calculamos las variables que usaran en la función FixedUpdate para indicarle a nuestro jugador que se mueva.
Para incorporar la posibilidad de controlar nuestro juego con el acelerometro tan solo tenemos que incorporar unas lineas, y tan solo tenemos que modificar la función Update. Vamos a ver como queda:

private void Update()
{
// Get the axis and jump input.
#if UNITY_STANDALONE
float h = CrossPlatformInputManager.GetAxis("Horizontal");
float v = CrossPlatformInputManager.GetAxis("Vertical");
jump = CrossPlatformInputManager.GetButton("Jump");
#else
//controles de android. 
float h = Input.acceleration.x;
float v = Input.acceleration.y;
jump = (Input.touchCount > 0);
#endif
// calculate move direction
if (cam != null)
{
// calculate camera relative direction to move:
camForward = Vector3.Scale(cam.forward, new Vector3(1, 0, 1)).normalized;
move = (v*camForward + h*cam.right).normalized;
}
else
{
// we use world-relative directions in the case of no main camera
move = (v*Vector3.forward + h*Vector3.right).normalized;
}
}

Primero podemos ver el uso de los preprocesadores. El código para MAC o Windows se ejecutara cuando creemos la aplicación para STANDALONE, para cualquier otra plataforma ejecutaremos el código contenido entre #else y #endif. Es decir, ese código se ejecutará cuando decida crear la versión para Android. La modificación no puede ser mas sencilla, para recuperar los datos Usamos el control Input y para el salto usamos Input.TouchCount que nos devuelve el numero de dedos que hay en la pantalla, en el caso de que se toque la pantalla con algún dedo, informamos la variable jump y nuestro protagonista saltará.

Probando los nuevos controles.

Para probar el acelerometro tenemos que crear nuestra aplicación para Android y tener nuestro teléfono con el modo de depurar USB activado conectado mediante USB a nuestra maquina. Para ver como preparar el entorno podeis leer el post: Desplegando nuestra aplicación Unity en android y WebGL..

También necesitaremos bajar en nuestro teléfono el programa Unity Remote y arrancarlo. Para que el IDE de Unity espere la entrada desde nuestro dispositivo tenemos que indicarlo en: edit->project settings->editor y escoger que device de Android queremos usar, o indicar any, es decir, cualquiera.

Ahora ya podemos ejecutar el juego como siempre, pero esta vez aunque se ejecute en nuestro entorno de desarrollo el control re hara desde el dispositivo que tenemos conectado 🙂

Esto es todo! En unos minutos hemos pasado de tener una aplicación para PC o MAC, a una aplicación multiplataforma que se puede ejecutar en Android usando el Acelerometro.  ¿Y si queremos crearla para Iphone? Solo son cambios de configuración y instalación de la plataforma, y optimizar las imagenes. Los script ya funcionan, no hace falta tocarlos.

Ole Unity!!

Comentarios.