Eventos basados en sistemas

Aprende cómo manejar los clics de usuario en tu escena.

Si tu escena tiene múltiples entidades similares que se activan usando la misma lógica, puedes escribir un único sistema que itere sobre todas ellas y describa ese comportamiento solo una vez. Esto también es lo más eficaz y más orientado a datos enfoque.

También puedes usar un sistema para detectar eventos de entrada globales, de modo que la escena reaccione cada vez que se presiona una tecla, sin considerar hacia dónde apunta el cursor del jugador.

Si lo único que quieres es hacer clic o pulsar un botón en una sola entidad para activarla, la forma más fácil es usar el Registrar un callback enfoque.

Para establecer una lógica personalizada más específica, quizá desees tratar los datos en bruto y usar el Advanced enfoque.

Para que una entidad sea interactiva, debe tener un collider. Ver obstáculos para más detalles.

Usando un sistema

Comprueba eventos de botón ejecutando una de las funciones auxiliares en el inputSystem namespace en cada tick dentro de un system.

Por ejemplo, el siguiente sistema usa el inputSystem.isTriggered() función para comprobar si se hizo clic con el puntero. En cada tick, comprueba si se presionó el botón. Si inputSystem.isTriggered() devuelve true, el sistema ejecuta alguna lógica personalizada en respuesta.

engine.addSystem(() => {
	if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN)) {
		// Lógica en respuesta a la pulsación del botón
	}
})

Las siguientes funciones auxiliares están disponibles en el inputSystem namespace, y pueden ser llamadas de forma similar en cada tick:

  • inputSystem.isTriggered: Devuelve true si ocurrió una acción de entrada desde el último tick.

  • inputSystem.isPressed: Devuelve true si una entrada se está manteniendo presionada actualmente. Devolverá true en cada tick hasta que el botón se suelte de nuevo.

  • inputSystem.getInputCommand: Devuelve un objeto con datos sobre la acción de entrada.

Consulta las secciones siguientes para obtener más detalles sobre cada una.

Al manejar eventos de botón en una entidad, siempre proporciona retroalimentación al jugador, para que el jugador sepa que una entidad puede interactuarse. Si añades un PointerEvents componente a una entidad, los jugadores verán una pista al pasar el cursor sobre esa entidad. Consulta Mostrar retroalimentación para aprender cómo puedes añadir pistas al pasar el cursor sobre entidades interactivas.

Eventos de entrada globales

Usa inputSystem.isTriggered para detectar eventos de botón pulsado y liberado en cualquiera de las entradas rastreadas por el SDK.

El ejemplo anterior comprueba si se presionó el botón, independientemente de dónde esté el puntero o qué entidades puedan estar en su trayectoria.

inputSystem.isTriggered() devuelve true solo si el botón indicado se presionó en el tick actual del bucle de juego. Si el botón no fue pulsado, o ya estaba pulsado desde el tick anterior, devuelve false.

circle-exclamation

El inputSystem.isTriggered la función toma los siguientes argumentos obligatorios:

  • InputAction: Qué entrada escuchar, como un valor del InputAction enum. Ver Botones del puntero para las opciones compatibles.

  • PointerEventType: Qué tipo de evento escuchar, como un valor de PointerEventType enum. Ver Tipos de eventos de puntero para las opciones compatibles.

Activar una entidad

Para detectar eventos de botón al apuntar a una entidad en particular, pasa un tercer argumento opcional a inputSystem.isTriggered para especificar qué entidad comprobar.

El ejemplo anterior comprueba en cada tick si una única entidad codificada fue pulsada con el botón del puntero (botón izquierdo del ratón).

El inputSystem.isTriggered function takes the following arguments:

  • InputAction: Qué entrada escuchar, como un valor del InputAction enum. Ver Botones del puntero para las opciones compatibles.

  • PointerEventType: Qué tipo de evento escuchar, como un valor de PointerEventType enum. Ver Tipos de eventos de puntero para las opciones compatibles.

  • Entity (opcional): Qué entidad comprobar para estos eventos. Si no se proporciona ningún valor, comprobará las pulsaciones globales del botón, sin importar hacia dónde apuntaba el cursor del jugador.

Ten en cuenta que en este ejemplo también estamos añadiendo un PointerEvents componente a la entidad con la que queremos interactuar. Este paso es necesario; sin este componente la entidad no será detectable por ninguna de las funciones de inputSystem. ver Mostrar retroalimentación para más detalles sobre el PointerEvents component.

circle-exclamation

Si hay múltiples entidades con las que el jugador puede interactuar de la misma manera, considera usar inputSystem.getInputCommand. Este comando devuelve información sobre un comando de clic global, incluyendo el ID de la entidad; puedes usar esto para ejecutar una única función que pueda manejarlas a todas.

circle-exclamation

Ver Datos de la acción de entrada para más información. Este método también te ofrece datos más detallados sobre el impacto del evento del puntero.

Botón de entrada liberado

También puedes comprobar eventos de puntero al soltar el botón de forma muy similar, usando PointerEventType.PET_UP.

circle-exclamation

Comprobar botones presionados

Comprueba si un botón se está manteniendo presionado usando inputSystem.isPressed() dentro de un sistema.

inputSystem.isPressed() devuelve true si el botón se está manteniendo presionado actualmente, sin importar cuándo se pulsó y sin importar hacia dónde apunta el cursor del jugador. De lo contrario devuelve false.

El inputSystem.isPressed la función toma un único argumento:

  • InputAction: Qué entrada escuchar, como un valor del InputAction enum. Ver Botones del puntero para las opciones compatibles.

Manejar múltiples entidades

Si tu escena tiene múltiples entidades que se ven afectadas por eventos de puntero de la misma manera, tiene sentido escribir un sistema que itere sobre todas ellas.

Este ejemplo usa un consulta de componentes para iterar sobre todas las entidades con un PointerEvents componente. Luego comprueba cada una de estas entidades con inputSystem.isTriggered, iterando sobre ellas una por una. Si se detecta una acción de entrada en cualquiera de estas entidades, se ejecuta la lógica personalizada.

En lugar de iterar sobre todos las entidades con un PointerEvents componente en un solo sistema, quizá quieras escribir sistemas diferentes para manejar entidades que deben comportarse de distintas maneras. El enfoque recomendado es marcar distintos tipos de entidades con componentes personalizados, y iterar sobre ellos en sistemas separados.

Este ejemplo tiene un sistema que itera sobre todas las entidades que tienen un componente personalizado llamado IsDoor y otro que itera sobre todas las entidades que tienen un componente personalizado llamado isGem. En ambos sistemas, comprueba cada entidad coincidente para ver si fueron activadas con el botón del puntero.

Esta forma de organizar el código de tu escena es muy orientado a datos y debería resultar en un uso muy eficiente de los recursos de memoria.

Mostrar retroalimentación

Para mostrar pistas de UI mientras se apunta a una entidad, usa las propiedades en el PointerEvents component.

Siempre que el cursor del jugador apunte a los colisionadores de esta entidad, la UI mostrará una pista al pasar el cursor para indicar que la entidad puede interactuarse. Consulta las secciones siguientes para detalles sobre lo que puedes configurar.

circle-exclamation

El PointerEvents el componente requiere al menos una definición de evento de puntero. Cada definición de evento de puntero puede configurarse con lo siguiente:

  • eventType: Qué tipo de evento escuchar, como un valor de PointerEventType enum. Ver Tipos de eventos de puntero para las opciones compatibles.

  • eventInfo: Un objeto que puede contener los siguientes campos:

    • botón (requerido): Qué entrada escuchar, como un valor del InputAction enum. Ver Botones del puntero para las opciones compatibles.

    • hoverText (opcional): Qué cadena mostrar en la pista de retroalimentación al pasar el cursor. "Interact" por defecto.

    • hideFeedback (opcional): Si es true, oculta tanto la pista al pasar el cursor como el resaltado de borde para esta entidad. false por defecto.

    • showHighlight (opcional): Si es true, los jugadores verán el resaltado de borde al pasar el cursor sobre la entidad. true por defecto. Este valor solo se considera si hideFeedback es false.

    • maxDistance (opcional): Mostrar retroalimentación solo cuando el jugador esté más cerca que cierta distancia de la entidad. Por defecto es 10 metros.

Un único PointerEvents componente puede contener múltiples definiciones de eventos de puntero, que pueden detectar diferentes eventos para distintos botones. Cada entidad solo puede tener uno PointerEvents componente, pero este componente puede incluir múltiples objetos en su pointerEvents matriz, uno por cada evento al que responder.

Los jugadores verán múltiples etiquetas, una por cada evento de puntero, mostradas radialmente alrededor del cursor.

El ejemplo a continuación combina el uso de PointerEvents para mostrar pistas al pasar el cursor, junto con un sistema que maneja la acción del jugador con lógica personalizada.

Feedback al pasar el cursor

Cuando un jugador pasa el cursor sobre un elemento con un PointerEvents componente, ve:

  • Un resaltado de borde en la entidad

  • Una pista junto al cursor con un icono para el botón que necesita pulsar y una cadena que dice "Interact".

Estos elementos pueden alternarse y personalizarse.

La retroalimentación al pasar el cursor en la UI muestra un icono diferente dependiendo de qué entrada selecciones en el botón campo. En PC, muestra un icono con un E para InputAction.IA_PRIMARY, un F para InputAction.IA_SECONDARY, y un ratón para InputAction.IA_POINTER.

Cambia la cadena cambiando el valor de hoverText . Mantén esta cadena corta, para que sea rápido de leer y no demasiado intrusiva en la pantalla.

En el ejemplo anterior, el evento de puntero incluye un valor para hoverText. Este campo define la cadena que se muestra en la UI mientras el jugador apunta a la entidad. Por defecto, esta cadena dice Interact.

circle-info

💡 Tip: El hoverText la cadena debe describir la acción que ocurre al interactuar. Por ejemplo Open, Activate, Agarrar, Selecciona. Estas cadenas deben ser lo más cortas posible, para evitar robar demasiado la atención del jugador.

Si una entidad tiene múltiples eventos de puntero, las pistas para cada uno de ellos se muestran radialmente alrededor del cursor.

El hoverText de un .UP el evento de puntero solo se muestra mientras el jugador ya está manteniendo pulsada la tecla correspondiente y apuntando a la entidad.

Si una entidad tiene tanto un DOWN evento de puntero y un UP evento de puntero, la pista para la DOWN acción se muestra mientras el botón no está siendo pulsado. La pista cambia a la del UP evento solo cuando el botón está presionado y se mantiene presionado.

Para ocultar la pista al pasar el cursor, pero dejar el resaltado de borde, establece el valor de hoverText a "".

Para ocultar el resaltado de borde pero dejar la pista al pasar el cursor, establece showHighlight a false.

Para ocultar tanto la pista al pasar el cursor como el resaltado de borde, establece hideFeedback a true. Al hacer esto, el cursor no muestra iconos, texto ni resaltado de borde. También podrías simplemente eliminar el PointerEvents componente de la entidad.

Distancia máxima

Algunas entidades pueden ser intencionalmente interactivas solo a corta distancia. Si un jugador está demasiado lejos de una entidad, la pista no se mostrará junto al cursor.

Por defecto, las entidades solo son clicables cuando el jugador está dentro de un rango cercano de la entidad, a una distancia máxima de 10 metros. Puedes cambiar la distancia máxima estableciendo la maxDistance propiedad de un evento de puntero.

El ejemplo anterior establece la distancia máxima para las pistas al pasar el cursor en 6 metros. Asegúrate de que la lógica para manejar las acciones de entrada también siga las mismas reglas. Consulta Datos de la acción de entrada para saber cómo obtener la distancia de una acción de entrada.

circle-exclamation

Pistas personalizadas avanzadas

El PointerEvents el componente añade fácilmente pistas de UI cuando el cursor del jugador comienza a pasar sobre una entidad. En general es bueno que las pistas se comporten de manera consistente con lo que los jugadores esperan ver en otras escenas de Decentraland. Sin embargo, en algunos casos podrías querer señalar que algo es interactivo de una manera personalizada. Por ejemplo, podrías reproducir un sonido sutil cuando el jugador comienza a pasar el cursor sobre la entidad. También podrías mostrar un resplandor alrededor de la entidad mientras se pasa el cursor, y ocultarlo cuando deje de pasar. También podría usarse para mecánicas de juego específicas.

Usa la inputSystem.isTriggered() función junto con los PointerEventType.PET_HOVER_ENTER y PointerEventType.PET_HOVER_LEAVE eventos para llevar a cabo comportamientos personalizados cada vez que el cursor del jugador comienza a apuntar al colisionador de la entidad y cada vez que el cursor deja de apuntarlo.

El ejemplo a continuación agranda las entidades a un tamaño de 1.5 cuando el cursor comienza a apuntar a su colisionador, y las devuelve a un tamaño de 1 cuando el cursor las abandona.

circle-exclamation

Datos de la acción de entrada

Obtén datos de una acción de entrada, como el botón que se pulsó, la entidad que fue golpeada, la dirección y la longitud del rayo, etc. Consulta (Ver documentaciónarrow-up-right) para una descripción de todos los datos disponibles.

Para obtener estos datos, usa inputSystem.getInputCommand. Esta función devuelve la estructura de datos completa con información sobre el evento de entrada.

Si no hubo ninguna acción de entrada que coincida con la consulta, entonces inputSystem.getInputCommand devuelve undefined. Asegúrate de manejar este escenario en tu lógica.

Distancia máxima de clic

Para aplicar una distancia máxima, de modo que una entidad sea clicable solo a corta distancia, obtiene la propiedad hit.length del datos del evento.

circle-exclamation

Mallas diferentes dentro de un modelo

A menudo, .glTF los modelos 3D están compuestos por múltiples mallas, que cada una tiene un nombre interno individual. Todos los eventos de botón incluyen la información de qué malla específica fue clicada, por lo que puedes usar esta información para activar comportamientos de clic diferentes en cada caso.

Para ver cómo se nombran las mallas dentro del modelo, debes abrir el modelo 3D con una herramienta de edición, como Blenderarrow-up-right por ejemplo.


circle-info

💡 Tip: También puedes aprender el nombre de la malla clicada registrándolo en la consola y leyéndolo desde allí.

Accedes a la meshName propiedad como parte del hit objeto, que es devuelto por el evento de clic.

En el ejemplo de abajo tenemos un modelo de casa que incluye una malla llamada firePlace. Queremos encender la chimenea solo cuando su malla correspondiente sea clicada.

circle-exclamation

Última actualización