El tutor de nuestro curso online de Desarrollo de Aplicaciones para Android, Víctor Ramírez Las,…
Input multiplataforma para videojuegos Unity
5.
Input multiplataforma para videojuegos Unity
En el desarrollo de un videojuego, gran parte del éxito viene determinado por la interacción que se proporciona al usuario a través del sistema de entradas o inputs, por los que será de gran relevancia definir correctamente dicho sistema de control.
Unity como herramienta para el desarrollo de videojuegos, soporta diferentes dispositivos de entradas, desde los más convencionales como el ratón, teclado, pasando por el joystick o el gamepad a los más específicos para dispositivos móviles, como la pulsación de la pantalla táctil o el acelerómetro del propio smartphone.
A continuación, se mostrarán los dispositivos de entrada soportados por Unity, además de visualizar y describir las propiedades que definen los ejes por defecto que se pueden encontrar en un nuevo proyecto.
Input convencional
Desde Unity es posible la configuración de entradas como el ratón, un teclado y un gamepad o mando de videojuego.
Es posible acceder a los diferentes ejes y botones virtuales ya definidos en un proyecto básico de Unity, a través del menú Edit > Project Settings… > Input, y mostrará una ventana similar a la siguiente con los ejes por defecto:
Se utilizará uno de los elementos ya definidos como ejemplo, para describir las propiedades que permitirán crear inputs personalizados. Para la creación de un nuevo eje, bastará con aumentar el número de elementos en 1 (propiedad Size), creándose un duplicado del ultimo eje de la lista, que nos permitirán definir una entrada personalizada para el manejo de un personaje en el videojuego y poder referenciar un input a través del nombre del eje para acceder a él mediante un script.
En la siguiente imagen se muestran las propiedades disponibles para la configuración personalizada de las acciones del juego:
Vamos a describir estas propiedades para la construcción o configuración de un eje en la siguiente tabla:
Propiedad | Función |
Name | Nombre del eje para su acceso desde un script. |
Descriptive Name | Nombre que se mostrará al usuario para la configuración. |
Descriptive Negative Name | Nombre para el botón negativo que se mostrará al usuario para la configuración. |
Negative Button | Botón para el movimiento del eje en sentido negativo. |
Positive Button | Botón para el movimiento del eje en sentido positivo. |
Alt Negative Button | Botón alternativo para el movimiento del eje en sentido negativo. |
Alt Positive Button | Botón alternativo para el movimiento del eje en sentido positivo. |
Gravity | Valor que permite establecer la velocidad en unidades por segundo de caída del eje hacia una posición neutra, al no pulsar ningún botón (velocidad de centrado del input). |
Dead | Valor que define el tamaño de la zona muerta análoga (rango de valores que al modificar el valor de entrada, no se apreciarán cambios observables en el valor de salida), estableciendo un rango para la posición neutral. Cualquier valor menor que este número se registrará como 0. |
Sensitivity | Establece la velocidad en unidades por segundo para controlar el movimiento del eje hacia la posición de destino (sólo para dispositivos digitales). Por ejemplo en un teclado, un valor mayor implica una respuesta más rápida. |
Snap | Al activar esta propiedad, permite el reseteo del eje y establecer su valor en cero, al recibir una entrada en dirección opuesta (sólo disponible para entradas de ratón y teclado). Como ejemplo, si nos encontramos manejando un personaje pulsando la tecla up, y a continuación se pulsa la tecla down, el valor del eje se establecerá a cero, deteniendo el movimiento del personaje. |
Invert | Invertirá los valores negativos a positivos y viceversa. |
Type | Tipo de input que controlará el eje. Los valores que pueden establecerse son del tipo Key or Mouse Button, para cualquier botón, movimiento de ratón o rueda de desplazamiento, Mouse Movement, para el movimiento sólo del ratón, y Joystick Axis, para los ejes analógicos del joystick. |
Axis | Eje de entrada del dispositivo (ratón, joystick, gamepad etc.). |
Joy Num | Joystick que será utilizado. Si se establece con el valor «Get Motion from all Joysticks», tomará todas las entradas de Joystick (sólo reconocerá como entradas los ejes y no los botones). |
Ejemplo de script (C#) para el uso de ejes de un input
Con el siguiente script, se mostrará el valor del eje de entrada a través de la consola, cuando el usuario pulse los botones left y right.
- En primer lugar (línea 3 del script que mostramos abajo) se comprueba el nombre del botón pulsado (lectura del botón pulsado)
- A continuación (línea 5), se almacena en la variable
value
el valor del eje virtual identificado por el nombre (lectura del eje). - Finalmente (línea 6), se mostrará por consola el valor del eje virtual cada vez que se pulsen los botones left o right.
1 2 3 4 5 6 7 8 9 |
while(true) { if(Input.GetButton("Horizontal")) { float value = Input.GetAxis("Horizontal"); print(value.ToString()); } } |
Input dispositivo móvil
En este apartado, se verán las particularidades de una plataforma móvil como es Android, en la que será necesario hacer uso de la clase Input, que proporciona acceso a los eventos táctiles de la pantalla, además del acelerómetro.
Una de las características que definen a los dispositivos móviles, y centrándose en las particularidades de la pantalla táctil de un smartphone Android, es la capacidad multi-touch que presentan todos los dispositivos, y que dependerá de su antigüedad para controlar un máximo de dedos simultáneamente en pantalla.
Entrada táctil de la pantalla
En la siguiente tabla, se describirán las propiedades y funciones disponibles para controlar los toques que realice el usuario en la pantalla del dispositivo:
Propiedad | Función |
fingerId | Identificador para el toque realizado en pantalla. |
position | Indica la posición en pantalla sobre la que se realiza la pulsación (ejes X e Y). |
deltaPosition | Controla el cambio de posición desde el último fotograma. |
deltaTime | El tiempo que ha pasado desde el último cambio de estado. |
tapCount | Contador, que a diferencia de los dispositivos IOS, en Android este valor será constante establecido en 1, ya que no es posible contabilizar el número de toques. |
phase | Describe el estado de la pulsación realizada en la pantalla. |
A continuación, se describirán los posibles valores de la propiedad phase:
Propiedad | Función |
Began | Controla el estado inicial de la pulsación. |
Moved | Controla el desplazamiento del dedo del usuario a lo largo de la pantalla estando pulsándola (movimiento desde el último evento). |
Stationary | Define la pulsación de un dedo en la pantalla, pero sin modificar su posición desde el último frame. |
Ended | Controla cuando el usuario levanta el dedo de la pantalla. |
Canceled | Es la última fase del proceso de pulsación de la pantalla, que cancelará el rastreo del dedo o cuando supere el número de pulsaciones capaz de detectar. |
Ejemplo de script (C#) para el control del estado inicial de la pulsación:
En el siguiente ejemplo, y dentro del método Update()
, lanzado en cada frame del juego, se mostrarán efectos de partículas (rayo) en el objeto que implemente el script, cuando el usuario toque con un dedo la pantalla:
- Para ello, se declara inicialmente un GameObject (línea 4 del script de abajo), al que posteriormente se asignará el efecto de partículas del que se disponga en los recursos del proyecto, a través del inspector del GameObject que implemente el script.
- A continuación, mediante el bucle foreach (línea 9), se recorre la lista de objetos que representan el estado de todas las pulsaciones de pantalla del último frame.
- Mediante una estructura condicional se comprueba si se encuentra en un estado inicial de pulsación (línea 10), para por último crear una instancia del sistema de partículas inicializado desde el inspector de Unity (línea 15).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using UnityEngine; using System.Collections; public class Ejemplo : MonoBehaviour { public GameObject particle; void Update () { foreach(Touch touch in Input.touches) { if (touch.phase == TouchPhase.Began) { Ray ray= Camera.main.ScreenPointToRay(touch.position); if (Physics.Raycast(ray)) { Instantiate (particle, transform.position, transform.rotation); } } } } } |
Acelerómetro
Como posiblemente sepas, un acelerómetro, es un sensor capaz de medir el movimiento del teléfono móvil en los 3 ejes. Dicho sensor mide los valores de los ejes X, Y, Z al modificar la orientación del dispositivo (aceleración).
Pues bien, una de las posibilidades que nos ofrece el acelerómetro es usarlo como input para el control de una aplicación, en este caso un videojuego, recuperando esos valores de los ejes X, Y, Z, a través de la propiedad Input.acceleration para asignarlos a un objeto del juego:
Además, es posible controlar que las lecturas de los valores devueltos por el acelerómetro, sean más concretos y eviten la implementación de un control menos preciso (filtro low-pass). Para ello, se muestra un script que permite suavizar los valores devueltos por el acelerómetro del dispositivo para un mayor control, filtrando las oscilaciones básicas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using UnityEngine; using System.Collections; public class AcelerometroLowPass : MonoBehaviour { float AccelerometerUpdateInterval = 1.0f / 60.0f; float LowPassKernelWidthInSeconds = 1.0f; private float LowPassFilterFactor = AccelerometerUpdateInterval / LowPassKernelWidthInSeconds; private Vector3 lowPassValue = Vector3.zero; void Start () { lowPassValue = Input.acceleration; } Vector3 LowPassFilterAccelerometer (){ lowPassValue = Mathf.Lerp(lowPassValue, Input.acceleration, LowPassFilterFactor); return lowPassValue; } } |
Créditos: imagen ejes acelerómetro de Android Developers (Creative Commons 2.5 Attribution License) . Los scripts C# se han creado a partir de código ejemplo Javascript que aparece en la documentación oficial de Unity