Jump to content
Sign in to follow this  
lightbug

Componente UnityInput

Recommended Posts

Hola, recientemente me di cuenta de que se puede cargar el asset llamado "InputManager" y meterse en las propiedades internas :) , la cuestión es que hoy empecé a probar y terminé haciendo este lindo componente muy simple que soluciona algunos problemas básicos y muchas veces molesto pasando las strings a los GetButton y los GetAxis.

¿Qué hace?

Basicamente permite interactuar con un campo "UnityInput" (clase de C#), este campo muestra todas las inputs disponibles, registradas en el InputManager. Los elementos son visualizados en forma de "popup" (como en un Enum). El usuario puede seleccionar directamente la Input registrada y no tener que andar metiendo strings (es necesario configurar las inpus en el InputManager).

¿Como se usa?

Muy simple. Por ejemplo se quiere tener dos ejes (Horizontal y Vertical) y dos botones (Jump y Run). Se definen como UnityInput:

Regístrate para acceder a este contenido.

0.JPG

Aparecen todos en Horizontal porque es el primer eje que encuentra. Luego se selecciona el eje de cada input:

2.jpg

1.JPG

Para obtener el estado por código se llama a los métodos públicos de la instancia. Por supuesto se le pueden agregar más cosas dentro. Por Ej:

Regístrate para acceder a este contenido.

 

  • Name: Retorna el nombre del eje.
  • Type: Retorna el tipo ( KeyOrMouseButton,   MouseMovement,  JoystickAxis ).

 

Código:

"InputManagerAsset.cs"

Regístrate para acceder a este contenido.

"UnityInput.cs"

Regístrate para acceder a este contenido.

No es la gran cosa pero puede servir.

 

Saludos

  • Like 1

Share this post


Link to post
Share on other sites

Está genial, y encima con el tema de los Presets ganará un montón. ¡Buen trabajo, como siempre! :27_sunglasses::91_thumbsup:

 

Yo hace nada estuve buscando información sobre unos eventos de Input que (se supone) devuelve el EventSystems y que se usan para la navegación entre botones de menús con el Canvas.  Con un pequeño apaño, eso nos daría eventos automáticos de algunos controles, y nos ahorraría algo de código para Analytics...

Yo no conseguí hacerlo funcionar, pero igual tú tienes más conocimientos y puedes entenderlo mejor cómo funciona, a ver...

Regístrate para acceder a este contenido.

 

 

Share this post


Link to post
Share on other sites
6 hours ago, pioj said:

Está genial, y encima con el tema de los Presets ganará un montón. ¡Buen trabajo, como siempre! :27_sunglasses::91_thumbsup:

 

Yo hace nada estuve buscando información sobre unos eventos de Input que (se supone) devuelve el EventSystems y que se usan para la navegación entre botones de menús con el Canvas.  Con un pequeño apaño, eso nos daría eventos automáticos de algunos controles, y nos ahorraría algo de código para Analytics...

Yo no conseguí hacerlo funcionar, pero igual tú tienes más conocimientos y puedes entenderlo mejor cómo funciona, a ver...

Regístrate para acceder a este contenido.

 

 

Gracias Pioj!

A lo tuyo, ¿Qué fue lo que no funcionó?¿Algún evento en concreto? me parece que OnMove se usaba para navegación (creo haberlo usado hace algún tiempo, no estoy seguro).

Share this post


Link to post
Share on other sites

Lo implementé pero no conseguí obtener ningún resultado visible, no me daba la respuesta del evento, como si no lo detectara.

Lo que quiero hacer es tener automáticamente eventos de navegación para no tener que crearlos yo, y conseguir ahorrarme código de Input. Me explico:

 

En lugar de hacer un If(Input.GetAxis("Horizontal")) en el Update, lo que quiero es que se ejecute una función decalarada en mi script, asociada al evento OnMove, y luego evaluar en esa función si la dirección era a la derecha o izquierda, etc. O sea, que no haya de invocar expresamente por código a los eventos ni tampoco implementar la detección de movimiento en ningún Update, ahorrándome esa evaluación, y ganando rendimiento.

Sí, ya sé que es algo limitado en cuanto a botones y a direcciones, pero con eso ya me sirve, de momento...

 

Se supone que el EventSystems los crea automáticamente, así que sólo tienes que recibirlos...

Share this post


Link to post
Share on other sites
3 hours ago, pioj said:

Lo que quiero hacer es tener automáticamente eventos de navegación para no tener que crearlos yo

Con OnMove se puede hacer eso, hasta ahí vamos.

3 hours ago, pioj said:

lo que quiero es que se ejecute una función decalarada en mi script, asociada al evento OnMove, y luego evaluar en esa función si la dirección era a la derecha o izquierda, etc ...

Ponele, en este caso se evalua sobre OnMove, para mostrar un ejemplo más general:

Regístrate para acceder a este contenido.

Esto va sobre el elemento que te interesa. Cada vez que se da OnMove te imprime la dirección de teclado (se usa eventData, con eso le sacás toda la info al evento). Si necesitas hacerlo más Inpector-Friendly podés meter más eventos UnityEngine.Events:

Regístrate para acceder a este contenido.

Si no querés meter tus funciones dentro de cada case, podés usar Eventos (UnityEvents) para llamar método de otras clases. Por ej (solo con Right):

Regístrate para acceder a este contenido.

Y para el case:

Regístrate para acceder a este contenido.

Entonces por cada elemento le podés definir una acción dependiendo de la dirección sin ningun Update ni nada (asumo que ya sebés definir los eventos en el inspector).

Para el caso de evaluar la dirección directamente en la función de destino simplemente necesitas enviar el entero casteado del enum MoveDirection (o el valor, como te guste llamarlo). Podés pasar nada, enteros, string y floats (creo) En tu función harás el switch y demás.

No se si era eso o me fui por las ramas xD.

 

Share this post


Link to post
Share on other sites
  1. IMoveHandler ¿se llama aún cuando no se realiza ningún movimiento?, es decir, se trata de un event ¿before o after?, 
  2. ¿se puede hacer un "preventDefault()" del evento para que este se marque como utilizado?
  3. ¿se puede obtener el contexto del evento o este 'Componente' necesita estar en cada GameObject que requiera el comportamiento?
  4. De ser falsa la (3).
    1. No sería conveniente utilizar un componente para manejar UI de forma más ordenada.
    2. De estar de acuerdo con (4.1)
      1. Sería bueno utilizar un Función Update global para todos los "Panel Context" de la interfaz de usuario y al inicio de cada update crear una estructura de evento, es más, creo que esto sería un poco mas optimo que la suscripción de eventos.

 

De todos modos la interfaz de UI de Unity aún tiene mucho trabajo por delante para ser una herramienta útil para el diseño... Habrá que ver en un futuro como se comporta ElementUI.

Solo una opinión....  Tendrías que abrir una sección exclusiva "User Interface" y ahí empezar a crear topics de mejores prácticas o ideas para organizar todo, me refiero, estructura, data binding, events, optimizations, contexts... etc......

 

Saludos!

Share this post


Link to post
Share on other sites
3 hours ago, lightbug said:

public void OnMove(AxisEventData eventData) { print( eventData.moveDir ); }

Esto es justamente lo que implementé de ejemplo, pero no me devolvió absolutamente nada por el DebugLog...

 

Lo acabo de volver a probar ahora mismo, y no sucede nada. ¿Qué hago mal, o qué me falta?

Regístrate para acceder a este contenido.

 

Share this post


Link to post
Share on other sites
1 hour ago, francoe1 said:
  1. IMoveHandler ¿se llama aún cuando no se realiza ningún movimiento?, es decir, se trata de un event ¿before o after?, 
  2. ¿se puede hacer un "preventDefault()" del evento para que este se marque como utilizado?
  3. ¿se puede obtener el contexto del evento o este 'Componente' necesita estar en cada GameObject que requiera el comportamiento?
  4. De ser falsa la (3).
    1. No sería conveniente utilizar un componente para manejar UI de forma más ordenada.
    2. De estar de acuerdo con (4.1)
      1. Sería bueno utilizar un Función Update global para todos los "Panel Context" de la interfaz de usuario y al inicio de cada update crear una estructura de evento, es más, creo que esto sería un poco mas optimo que la suscripción de eventos.

1 - Según la API dice cuando "ocurre". Tampoco no se en que casos tener la info precisa pueda resultar de vital importancia (quizás tengas algo en mente, no se me ocurre nada ahora).

2 Ni idea que es el "preventDefault", te referís a un estilo "event.Use" ? Si es esto, creo que el evento se "usa" para el mismo gameObject. Si probás un OnPointEnter en un script A junto con un componente "Button" (que ya lo usa para el highlight) el OnPointerEnter no se ejecuta en el script A (Ojo tendría que probarlo nuevamente, pero recuerdo que algo así pasó).

3 - Mmm mepa que no.

4.1 Manejar la UI de forma ordenada??? ... Donde firmo?

4.2 Te referís a trabajar en un contexto de grupo de elementos y no de elemento? cosa que todo se registre en un marco global y no andar pasando datos de un elemento a otro? si es así desde ya que lo veo mejor.

13 minutes ago, pioj said:

Esto es justamente lo que implementé de ejemplo, pero no me devolvió absolutamente nada por el DebugLog... Lo volveré a revisar mañana, a ver...

¿Estás seguro que navegabas bien por la UI? solo se corre en el elemento que tiene el script, caundo apretás las teclas (más allá de que haya o no caminos disponibles). Si usas botones ponele el highlight en algun color llamativo. Primero seleccioná algun elemento y empezá a moverte.

Share this post


Link to post
Share on other sites
3 hours ago, pioj said:

Lo acabo de volver a probar ahora mismo, y no sucede nada. ¿Qué hago mal, o qué me falta?

Regístrate para acceder a este contenido.

pregunto, una muy tonta que me pasó una vez, tenés activado los Logs de consola no? (al lado de warnings y errores). Se que suena tonto pero una vez estuve todo un día con ese problema.

El código está bien. Si estás disparando correctamente los events debería dar el print.

EDIT: Pensé que el post se iba a unir al anterior :51_scream:  Otras veces a pasado, me disculpo.

Edited by lightbug

Share this post


Link to post
Share on other sites

Lo que puede ser es que el script deba estar agregado a los botones en sí, pero entonces ya no me serviría para nada. Lo que quiero es capturar eventos remotos, no propios...

Si queréis seguir investigando el tema, y tenéis a mano algún ejemplo que os funcione, ponedlo por aquí, pls....

 

2 hours ago, lightbug said:

Pensé que el post se iba a unir al anterior :51_scream:  Otras veces a pasado, me disculpo.

Hay un tiempo mínimo de posteo para que lo haga. Creo que si pasa más de 1h , ya lo trata como un post separado. Igualmente, yo suelo unir algunos a mano, cuando los veo...

 

 

Por cierto, volviendo al tema del Topic en sí, yo he probado a declarar variables de tipo Keycode, para asignarlas desde el Inspector. Pero no lo recomiendo en absoluto, porque la navegación entre teclas es MUY lenta. Hubiera estado genial encontrar un PropertyAttribute que soporte quicksearch para que filtre directamente sobre la tecla pulsada en ese momento...

Share this post


Link to post
Share on other sites
6 hours ago, pioj said:

Por cierto, volviendo al tema del Topic en sí, yo he probado a declarar variables de tipo Keycode, para asignarlas desde el Inspector. Pero no lo recomiendo en absoluto, porque la navegación entre teclas es MUY lenta. Hubiera estado genial encontrar un PropertyAttribute que soporte quicksearch para que filtre directamente sobre la tecla pulsada en ese momento...

Regístrate para acceder a este contenido.

Gif animado aquí (no me deja adjuntarlo): 

Regístrate para acceder a este contenido.

Y el que quieres exactamente sería este: 

Regístrate para acceder a este contenido.

Edited by xeleh
  • Like 1

Share this post


Link to post
Share on other sites
12 minutes ago, xeleh said:

Regístrate para acceder a este contenido.

Regístrate para acceder a este contenido.
Gif animado aquí (no me deja adjuntarlo): 
Regístrate para acceder a este contenido.

Y el que quieres exactamente sería este: 

Regístrate para acceder a este contenido.

Muy buenas.

6 hours ago, pioj said:

Por cierto, volviendo al tema del Topic en sí, yo he probado a declarar variables de tipo Keycode, para asignarlas desde el Inspector. Pero no lo recomiendo en absoluto, porque la navegación entre teclas es MUY lenta. Hubiera estado genial encontrar un PropertyAttribute que soporte quicksearch para que filtre directamente sobre la tecla pulsada en ese momento...

Yo dejé de usar keycodes, por temas del asset store me preguntaban X asset funcionaba con Rewired (la típica), mi respuesta era "Ni idea". Averiguando Rewired puede reemplazar los típicos GetButton("Key") con su propia implementación, así que ahora todo lo hago por las dudas usando el Unity InputManager y listo. Para lo personal, recuerdo que (usando Keycodes) si quería la tecla "C" la presionaba y me mandaba a elementos con C, no era super rápido para definir de una a la KeyCode deseada, pero teniendo en cuenta que asignaba este campo 1 vez cada tres meses no era "él" problema.

El problema básico de esto es que usando Keycodes estás trabajando sobre el binding y no sobre la acción, pero bueno para cosas rápidas va bien.

7 hours ago, pioj said:

Lo que puede ser es que el script deba estar agregado a los botones en sí, pero entonces ya no me serviría para nada. Lo que quiero es capturar eventos remotos, no propios...

Si queréis seguir investigando el tema, y tenéis a mano algún ejemplo que os funcione, ponedlo por aquí, pls....

A claro, el componente con el script debe estar en el elemento. La cosa es que de ahí se puede redisparar algun evento que actualice algún contexto maestro, algun manager, o quién quiera recibir el evento (un evetn delegate por ej).

Regístrate para acceder a este contenido.

No se si es lo ideal, pero si querés hacer algo así usando el EventSystem actual  (con OnMove por ej) no le veo otra, o al menos no conozco otra forma.

Share this post


Link to post
Share on other sites
7 hours ago, pioj said:

Lo que puede ser es que el script deba estar agregado a los botones en sí, pero entonces ya no me serviría para nada. Lo que quiero es capturar eventos remotos, no propios...

Eso se puede hacer hasta cierto punto con los componentes Event System (agregándole después el Stand Alone Input Module y poniéndolo como activo) y Event Trigger, pero por lo que he visto no detecta eventos en plan global exactamente, sino sólo los emitidos por objetos dentro de su jerarquía, pero bueno, al menos te ahorras tener que agregar un script a cada objeto. Eso sí, cuidado porque parece que algunas de estas cosas de eventos cambiaron de la 2018 a la 2019. Yo he hecho un ejemplo tonto en la 2018.4 y en esa todavía funciona.

Ah, también necesitarás alguno de los componentes Raycaster en función de los eventos que quieras escuchar Si por ejemplo quieres eventos al hacer click sobre algún collider necesitarás un Physics Raycaster añadido a tu cámara.

Share this post


Link to post
Share on other sites
Sign in to follow this  

UnitySpain © Todos los derechos reservados 2020
×
×
  • Create New...