Activa JavaScript para disfrutar de los vídeos de la Mediateca.
Primeros pasos en Unity. Input System (parte 2) - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
Una vez visto cómo funciona el Input System, aprendamos cómo trasladar las acciones a código. Existen al menos 3 formas de hacerlo. Veamos la primera.
Bien, llevemos ese mapeo maravilloso que hemos hecho a código para poder, pues, programar.
00:00:07
Como ya comenté, vamos a ver tres métodos.
00:00:12
Empiezo con el que más me gusta a mí, ¿no?
00:00:15
Es el que aparece por defecto en la documentación de Unity, pero es válido.
00:00:17
Y a lo mejor yo lo uso porque es el primero que aprendí y, oye, ya sabemos que cuando tenemos un martillo entre las manos
00:00:21
todos nos parecen clavos, pero es válido.
00:00:26
Así que empiezo por ese y luego ya veremos otros dos, ya que cada uno elija.
00:00:28
para ello, volvemos otra vez al proyecto
00:00:33
y lo primero que haremos es
00:00:37
en ese asset de acciones que hemos creado
00:00:40
que por cierto, muy mal, no lo tenía dentro de su carpeta correspondiente
00:00:43
lo primero que vamos a hacer
00:00:47
es crear una clase con él
00:00:49
esto no es obligatorio en otros métodos, pero en el que vamos a hacer ahora, sí
00:00:51
es decir, no existe una clase pública a la que podamos llamar
00:00:55
con esos inputs, pero la podemos crear
00:00:58
si nos fijamos aquí, tenemos el botoncito de
00:01:01
generar una clase
00:01:03
que si lo seleccionamos
00:01:04
nos preguntará
00:01:07
dónde guardarla. Podemos cambiar
00:01:08
la carpeta. Por defecto la mete en el mismo
00:01:11
sitio que está el asset.
00:01:13
¿Cómo llamarlo? Por defecto lo llama
00:01:15
igual que el asset que hemos creado
00:01:17
pero que puede cambiarse igualmente.
00:01:19
Incluso se le puede dar un global name
00:01:22
space, que ni me meto en eso lo que es, pero sería
00:01:23
para la hora de llamarlo.
00:01:25
Las opciones que vienen por defecto a mí me valen, pero siempre
00:01:27
recordad que le está llamando igual que el archivo.
00:01:29
aplicar. Y veremos que
00:01:31
donde yo le he dicho, ha creado un archivo
00:01:34
de código que no debemos tocar.
00:01:37
Que quede claro. Eso no es para que lo abramos y lo toquemos.
00:01:41
No. Bien. Tengo un script
00:01:44
ya creado, al que he llamado PlayerManager.
00:01:47
Lo voy a abrir. Ahí está. Le he quitado el start y el update
00:01:50
para que no molesten. Y entonces, lo primero
00:01:53
que tenemos que hacer es acceder a esa nueva clase que hemos creado.
00:01:56
entonces es de tipo
00:01:59
inputActions porque la he llamado así
00:02:02
si la hemos llamado de otra forma será la clase de otra forma
00:02:05
será el que le hayamos dado y bueno ya sabéis que
00:02:08
por deferencia pues el mismo nombre
00:02:11
en minúscula para indicar que esa es la instancia de la clase
00:02:13
todo lo que tiene que ver con inputs lo normal es
00:02:17
llamarlo en el awake, ya veremos
00:02:20
porque no espera que cargue la escena, entonces en el awake
00:02:23
lo primero que tengo que hacer es crear una instancia de esa clase
00:02:26
entonces inputActions en minúscula
00:02:30
porque la instancia es igual a, cuidado que aquí Visual Studio
00:02:32
sugiere algo que no es
00:02:35
porque yo no tengo ese componente, yo no lo tengo, yo lo que tengo es que
00:02:38
crearlo, igual que cuando creamos una nueva instancia de un Vector3
00:02:41
o lo que sea, así que es un new inputActions
00:02:44
ahí está, ahora me voy a poner un poco serio
00:02:47
antes de seguir, esto que voy a hacer ahora
00:02:50
lo recomiendan en dos de las tres métodos que vamos a ver
00:02:53
y tenemos que entenderlo, porque si no lo hacemos no pasa nada, pero Unity
00:02:57
recomienda hacerlo, así que yo soy el mensajero
00:03:01
cada vez que activamos unas entradas realmente estamos escuchando
00:03:05
constantemente, entonces una medida de seguridad que tiene Unity es decirle
00:03:09
estas entradas activalas cuando el objeto que tiene este script
00:03:12
esté activo en la escena, antes no, y desactivalas
00:03:17
si ese objeto deja de estar activo
00:03:21
en la escena. De forma que
00:03:23
es una forma también de decir, oye, si
00:03:24
por lo que sea he desactivado
00:03:26
el objeto que tiene estas entradas, automáticamente
00:03:28
desactiva esos inputs
00:03:31
porque se supone que están vinculados a ese objeto.
00:03:33
Eso se hace utilizando
00:03:35
un método que hasta ahora no hemos usado
00:03:37
nunca, aunque sí que lo
00:03:39
hemos mencionado, que es onEnable
00:03:40
que funciona un poco igual que
00:03:43
el start o el away, pero que se lanza
00:03:44
cada vez que activo el objeto
00:03:47
que tiene el script. Es decir, si yo lo desactivase
00:03:48
y lo volviese a activar, saltaría
00:03:51
el onEnable. ¿Y qué hacemos
00:03:53
cuando me activo? Pues que ese
00:03:55
inputActions que hemos creado
00:03:57
lo activo. Ahí está.
00:03:58
Con su método de enable. Y lo mismo tengo que
00:04:01
hacer si desactivo.
00:04:03
Ahí está. Esto de aquí
00:04:06
lo tenemos que hacer siempre.
00:04:07
Y yo...
00:04:10
Da igual donde pongamos este código. Yo
00:04:11
siempre lo meto al final del script.
00:04:13
Me resulta más cómodo. Pero tiene que estar.
00:04:15
Tiene que estar.
00:04:17
Insisto, si no lo ponemos sigue funcionando, pero eso no significa que esté bien.
00:04:18
Bien, y ahora es donde empieza lo interesante, que es en el mismo Awake.
00:04:22
¿Cómo funciona este sistema que es el que a mí me gusta?
00:04:28
En el método Awake, ahora es cuando nosotros podemos llamar al inputActions
00:04:32
a un mapa de acciones en concreto, es decir, esta es la sintaxis, la instancia del input.
00:04:37
el mapa de acciones que hemos creado
00:04:45
os recuerdo que yo he creado una llamada player
00:04:47
entonces llamo a player
00:04:50
a continuación
00:04:52
la acción a la que quiero yo llamar
00:04:53
por ejemplo la de jump
00:04:56
el me autocompleta, sabe que está ahí
00:04:57
y ahora
00:05:00
tenemos
00:05:01
tres opciones
00:05:03
ahora que hemos llamado a una acción
00:05:05
una
00:05:08
cuando se inicia
00:05:08
pensemos en un botón, es cuando lo pulso
00:05:11
Dos, mientras se está ejecutando
00:05:13
En un botón sería mientras lo estoy pulsando
00:05:18
Pero pensemos más en un joystick
00:05:21
Mientras se esté moviendo ese joystick
00:05:22
Hay que hacer algo
00:05:24
Y tres, cuando dejo de pulsarlo
00:05:26
O cuando dejo de mover el joystick
00:05:28
El primero sería started
00:05:31
El segundo sería perform
00:05:32
Y el tercero sería cancel
00:05:34
Lo vamos a ver
00:05:36
Quiero que cuando pulse el botón de jump
00:05:38
Pase algo
00:05:40
Eso es started
00:05:41
y ahora, esta sintaxis es un poco extraña
00:05:42
pero vamos, ya llega un momento en que nos acostumbramos a ello
00:05:46
porque lo que necesitamos es que ocurra algo
00:05:48
entonces eso es un más igual porque
00:05:51
esto lo he mencionado porque tampoco quería liar mucho
00:05:54
pero este sistema utiliza callbacks, es decir, necesito que me devuelvas un valor
00:05:56
como el jump no me tiene que devolver nada
00:06:00
voy a poner una barra baja
00:06:04
más que nada porque es una convención para decir
00:06:06
mira, yo no necesito que me devuelvas nada, el callback no va a ser nada
00:06:09
igual y mayor que para hacer algo
00:06:12
después de obtenerse callback. ¿Qué quiero hacer después de esto?
00:06:15
Ahora veremos tres formas en las que tenemos para actuar una vez ya
00:06:20
llamada esa acción. Una, la más cómoda y más rápida, por eso he empezado
00:06:24
por el jam, llamar a un método. Por ejemplo, si yo creo un método que le llamo
00:06:28
saltar, en español para
00:06:33
distinguirlo del jam de la acción, aunque lo podría llamar jam igualmente
00:06:35
y voy a poner un envío a consola que es saltando
00:06:40
para comprobar que efectivamente se está ejecutando
00:06:43
pues bien, volvamos a la línea
00:06:46
la instancia de los inputs
00:06:49
el mapa de acciones, la acción y starter que se lanza
00:06:51
cuando inicio el salto
00:06:55
y llamo al método saltar
00:06:57
antes de seguir
00:07:03
y como yo sé que va a funcionar
00:07:05
voy a meter otro método que se llame
00:07:08
dejar de saltar
00:07:10
¿y cuándo se llama esto?
00:07:12
voy a llamar print
00:07:15
he dejado de saltar
00:07:16
¿y cuándo voy a llamar
00:07:19
a esto? cuando
00:07:22
deje de pulsar el botón
00:07:23
y eso es cancel
00:07:28
tenemos started y cancel, viene muy
00:07:29
bien, por ejemplo, para booleanas en las
00:07:32
que digo, oye, cuando pulse el botón esa booleana
00:07:33
es true y cuando pulse el botón esa booleana
00:07:36
es false, lo veremos también con un ejemplo
00:07:38
y esto llama
00:07:39
a dejar de saltar. Si todo va bien, si todo va bien, le doy al play. Había vinculado
00:07:41
el salto a la barra espaciadora, por ejemplo, entonces si pulso la barra espaciadora, efectivamente
00:07:50
me dice que está saltando y si suelto la barra espaciadora me dice que ha dejado de
00:07:54
saltar. Correcto. Y también funciona con la saltando, he dejado de saltar. ¿Qué ocurre
00:07:59
si, por ejemplo, como hemos dicho, quiero ahora hacer
00:08:06
un botón de agachado, que va a ser la B, por ejemplo.
00:08:10
Hacemos un repaso para que así veamos que es tremendamente fácil.
00:08:15
Si yo me voy a mi input system, lo abro, me voy a mi player
00:08:18
y voy a añadir una nueva acción que va a ser crouch, agachar.
00:08:22
¿Qué es un botón? Acordaros siempre de si es un botón o un value.
00:08:26
Binding, listen, botón B, que es el botón derecho
00:08:30
de cualquier gamepad
00:08:33
o que narices, puedo incluso añadir
00:08:35
una nueva acción y vincularlo con
00:08:37
el control
00:08:40
del teclado, ahora ya está, guardar
00:08:40
siempre que guardar, si no, no se aplican los cambios
00:08:43
y además
00:08:45
lo bueno es que actualiza la clase
00:08:47
que hemos creado previamente
00:08:49
eso significa que si me voy a mi
00:08:50
código, pues ya podría
00:08:53
llamarlos, pero antes de hacerlo y para que entendamos
00:08:55
otra funcionalidad
00:08:57
que tiene este sistema
00:09:00
voy a crear una booleana
00:09:00
creo que va a llamar crouched
00:09:02
agachado
00:09:04
le voy a decir por defecto que es false, aunque os recuerdo que
00:09:06
cuando a una booleana
00:09:09
no le decimos nada, él le entiende que por defecto es false
00:09:11
vamos a mis inputs
00:09:13
y le doy, oye, misma mecánica
00:09:14
input actions
00:09:17
dentro del mapa de acciones, player
00:09:18
veis que ahora aparece crouch, lo reconoce
00:09:20
la que ha acabado de crear, y started
00:09:23
esto no lo quiero
00:09:24
lo mismo
00:09:27
no necesito un callback, por eso pongo un guión bajo
00:09:28
pero
00:09:30
no quiero llamar a un método, quiero ejecutar un código. Entonces tenemos que entender
00:09:31
que si yo aquí pongo una llave, llave de apertura y llave de cierre
00:09:36
veréis que me da un error. ¿Por qué me da un error? Porque pide
00:09:40
un punto y coma para terminar. En algunos códigos no pide punto y coma para cerrar unas llaves
00:09:43
pero aquí sí. Entonces, lo voy a poner así para que sea más entendible
00:09:48
yo abro unas llaves, cierro unas llaves
00:09:54
y todo el código que meta aquí dentro de esas llaves se va a ejecutar
00:09:58
cuando pulse ese botón.
00:10:02
Por ejemplo, voy a mandar a consola
00:10:04
me agacho
00:10:06
y no solo eso, sino que voy a ponerle
00:10:08
que clauchet
00:10:12
es true.
00:10:12
Para que veamos que yo puedo poner
00:10:17
todas las líneas de código que conseguir oportuno.
00:10:18
De hecho, voy a duplicar,
00:10:20
ya sabéis, control D, y le voy a decir
00:10:22
que cuando deje de pulsar ese botón
00:10:24
cancel
00:10:26
manda consola
00:10:27
me levanto
00:10:29
y crouched será false
00:10:31
y podría poner más líneas de código
00:10:35
vamos a ver si funciona
00:10:37
y es más, para ver esto
00:10:38
de hecho voy a entrar en modo debug
00:10:39
porque al entrar en modo debug
00:10:42
me va a permitir ver
00:10:43
la variable crouched
00:10:45
vamos allá
00:10:49
botón B
00:10:50
efectivamente
00:10:51
me pone que crouched es true
00:10:54
como podemos ver ahí
00:10:55
y además me lo ha mandado a consola
00:10:56
y si lo suelto
00:10:57
se levanta
00:10:59
y crouched
00:11:00
es false. Vayamos al último
00:11:01
que es, vale, hasta ahora
00:11:04
hemos visto cómo puedo llamar un método y puedo
00:11:06
también ejecutar unas líneas de código
00:11:08
pero cuando necesito
00:11:10
recuperar un valor, pues la cosa
00:11:11
se complica. Para ello voy a crear
00:11:14
un vector2
00:11:16
que le voy a llamar move
00:11:18
entonces, teniendo
00:11:19
la variable
00:11:22
pues ahora en el inputActions
00:11:23
en la wake, le digo
00:11:25
inputActions
00:11:28
veremos que es bastante repetitivo
00:11:29
este método, este sistema, pero
00:11:31
una vez que lo hemos hecho una vez, hasta podemos repetirlo
00:11:33
para otros códigos
00:11:35
inputActions, player
00:11:36
move, que había creado
00:11:39
una acción llamada move, que era un vector2
00:11:41
no le voy a decir
00:11:43
starten, no me interesa
00:11:46
recibir cuando empieza
00:11:47
a recibir esa entrada
00:11:49
no, me interesa mientras la esté moviendo
00:11:51
eso es
00:11:53
perform
00:11:55
bien, más igual
00:11:56
y aquí es donde viene lo interesante
00:11:59
necesito un callback, necesito un valor
00:12:00
de retorno, entonces podría
00:12:02
ponerle un guión bajo, no tiene sentido
00:12:04
porque aquí se le suele poner context
00:12:06
es un nombre
00:12:08
que nosotros queramos, pero es verdad que
00:12:10
por convención se suele llamarle context
00:12:12
y es verdad que por convención
00:12:14
se le suele abreviar en ctx
00:12:16
para no escribir tanto
00:12:18
entonces ese es el valor que me va a devolver
00:12:20
igual, mayor que
00:12:23
la misma sintaxis, pero ahora, atentos, le tengo que decir
00:12:25
mi variable move
00:12:29
es igual a, me vas a ir a ese
00:12:32
callback que acabas de crear y vas a leer su
00:12:37
valor. Y entre menor y mayor que, tenemos que decirle
00:12:40
qué tipo de valor va a devolver. Y en este caso es un vector 2.
00:12:44
Esa es la sintaxis. Un poco farragosa, pero
00:12:50
ese es
00:12:53
ahora mismo move valdrá lo que me dé
00:12:55
el joystick, pero antes de comprobarlo
00:12:58
sé que va a funcionar, pero antes de comprobarlo
00:13:00
está recogiendo ese valor y funciona
00:13:02
pero cuando suelte el joystick
00:13:04
se va a quedar en el último valor
00:13:05
recogido, con lo cual nos va a ocurrir que
00:13:08
de repente estamos moviendo el personaje
00:13:09
suelto el joystick y el personaje se sigue moviendo
00:13:11
¿por qué? porque se ha quedado en el último
00:13:14
valor que tenía en ese momento
00:13:16
cuando lo solté, por eso para evitarlo
00:13:17
tenemos que decirle, voy a escribir todo el tirón
00:13:20
input actions
00:13:22
player move
00:13:23
cuando dejes de recibir
00:13:24
datos, es decir, en cancel
00:13:27
más igual
00:13:29
ahora no necesito un callback porque veremos
00:13:31
que no necesito un valor de vuelta
00:13:33
le tengo que decir cuando sueltes el joystick
00:13:34
move es igual a
00:13:36
en este caso es vector 2
00:13:37
0, es decir, un vector que valga 0, 0, 0
00:13:40
si fuese un float le diría
00:13:43
que ese valor es 0
00:13:44
es decir, en caso de ser un axis le diría
00:13:46
que ese float, como lo haya llamado
00:13:48
el walk, por ejemplo, valdría 0
00:13:50
Igual a 0. Pero en este caso es un vector 2, así que le tengo que decir que es vector 2, 0.
00:13:53
Bueno, y estoy tan seguro de que esto va a funcionar
00:13:58
que para comprobarlo, ni bug ni nada.
00:14:00
Directamente voy a crear en el update y le voy a decir que
00:14:04
muévete hacia adelante
00:14:11
por time delta time, por, muy importante,
00:14:16
lo que me diga move, pero atentos, que era un vector 2.
00:14:29
no es un float, si fuese un eje sí sería un float
00:14:32
es un vector 2, así que será su eje
00:14:35
y lo mismo
00:14:37
le diré, muévete a la derecha
00:14:41
por time delta time, porque es cinemático
00:14:43
y lo que me devuelvas en tu eje, x
00:14:48
vale, comprobémoslo, ahí está
00:14:51
para adelante, para atrás, derecha
00:14:58
izquierda, y movimiento
00:15:01
No le he dado ninguna velocidad, así que como me devuelve vectores normalizados, se está moviendo a un metro por segundo.
00:15:04
Pero bueno, eso ya es de otro capítulo.
00:15:11
Repasando.
00:15:13
Hemos creado una clase, aquí lo vemos.
00:15:14
Con esa clase que hemos creado y que tiene el mismo nombre que el archivo, hemos creado una instancia y en el Awake hemos generado esa instancia.
00:15:18
Antes de continuar, debemos asegurarnos que en Enable esa instancia se active y en Disable esa instancia se desactive.
00:15:27
Y a partir de ahí, en el Awake, podemos llamar a cualquiera de sus mapas de acciones y a cualquiera de sus acciones de tres formas.
00:15:36
Cuando empiezan, cuando se ejecutan y cuando dejan de ejecutarse.
00:15:45
Y con eso, mediante esta sintaxis, o bien llamar a un método, o bien abrir unas llaves y meter código dentro,
00:15:49
o bien, cuando queremos que nos devuelva un valor, crear una variable que será su callback, es decir, lo que devuelve,
00:15:58
Y darle ese callback mediante el read value a la variable que nosotros queramos, que obviamente tiene que ser del mismo tipo que la acción que hemos creado.
00:16:06
- Idioma/s:
- Materias:
- Informática, Imagen y Sonido
- Niveles educativos:
- ▼ Mostrar / ocultar niveles
- Formación Profesional
- Ciclo formativo de grado superior
- Primer Curso
- Segundo Curso
- Autor/es:
- Alvaro Holguera Gozalo
- Subido por:
- Alvaro H.
- Licencia:
- Reconocimiento - No comercial - Sin obra derivada
- Visualizaciones:
- 4
- Fecha:
- 9 de diciembre de 2025 - 11:21
- Visibilidad:
- Público
- Centro:
- CFP JOSÉ LUIS GARCI
- Duración:
- 16′ 17″
- Relación de aspecto:
- 1.78:1
- Resolución:
- 1920x1080 píxeles
- Tamaño:
- 660.91 MBytes