> For the complete documentation index, see [llms.txt](https://docs.decentraland.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.decentraland.org/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/click-events.md).

# Eventos de clic

Una escena de Decentraland puede detectar acciones de entrada de todos los botones que se usan para controlar el avatar del player. Estos incluyen clics del pointer, varios botones de acción y las teclas que se usan para mover el avatar. Los eventos de botón pueden venir de un mouse y teclado en el cliente de escritorio, de los controles en pantalla en la [aplicación móvil](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/building-for-mobile.md), desde un controlador de VR, o desde otros dispositivos de entrada — todo esto se interpreta igual por el SDK.

Puedes detectar acciones de entrada contra una Entity. Esto implica presionar un botón mientras el cursor del player apunta al collider de esa Entity. También puedes detectar *global* eventos de entrada, que implican presionar y activar la entrada en cualquier momento, sin tener en cuenta hacia dónde apunta el pointer.

{% hint style="warning" %}
**📔 Nota**: Las Entities deben tener un [collider](/creator/content-creator-es/escenas-sdk7/conceptos-basicos-de-contenido-3d/colliders.md) para responder a las acciones de entrada. `MeshRenderer` a los modelos también se les debe asignar un `MeshCollider` component. Los modelos de un `GltfContainer` pueden tener su propia geometría de colisión incrustada, o pueden configurarse para usar su geometría visible; también se les puede asignar un `MeshCollider` componente.
{% endhint %}

Hay varias formas distintas de manejar las acciones de entrada, según el caso de uso.

* [**Registrar un callback**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/register-callback.md): La forma más sencilla de añadir interacción a una sola Entity. Escribe una sola instrucción para configurar una función callback y la retroalimentación al pasar el cursor.
* [**basado en System**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/system-based-events.md): Ideal para manejar múltiples entities con comportamiento similar. Usa un System para iterar sobre entities similares y consultar las acciones de entrada de cada una, manejándolas todas con la misma lógica. La retroalimentación al pasar el cursor debe configurarse por separado. Este enfoque también es necesario para manejar acciones de entrada globales.
* [**Avanzado**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/advanced-button-events.md): Lee los datos de respuesta sin procesar en cada Entity, incluidos los time-stamps y un historial de eventos de entrada. Esto puede ser útil para definir patrones de interacción personalizados.

## Usa Scene Editor en Creator Hub

La forma más sencilla de manejar eventos de clic en una Entity es usar el Scene Editor. Usa el no-code **Al hacer clic** o **Al activar una acción de entrada** Los triggers en un item para llamar acciones al hacer clic sobre él. O usa **Al hacer clic global**, **Primario global** o **Secundario global** Triggers para reaccionar a eventos globales de botones. Consulta [Actions, consulta](/creator/content-creator-es/scene-editor/interactividad/make-any-item-smart.md).

## Ejemplo simple

Para detectar clics en una Entity, usa `pointerEventsSystem.onPointerDown`.

```ts
pointerEventsSystem.onPointerDown(
	{
		entity: myEntity,
		opts: { button: InputAction.IA_PRIMARY, hoverText: 'Haz clic' },
	},
	function () {
		console.log('se hizo clic en la entidad')
	}
)
```

Consulta [**Registrar un callback**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/register-callback.md) para más información.

## Retroalimentación al pasar el cursor

Es importante hacer que los players sepan que una Entity es interactiva. De lo contrario, podrían perder por completo la experiencia que construiste. No es una buena experiencia hacer clic en cada objeto con la esperanza de que alguno responda.

Cuando usas el [**Registrar un callback**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/register-callback.md) método, se muestran dos tipos de retroalimentación cada vez que el player pasa el cursor sobre el objeto:

* El borde de la Entity se resalta (solo en el cliente de escritorio de Decentraland 2.0). El resaltado es verde si la Entity está lo suficientemente cerca para hacer clic, rojo si la Entity está demasiado lejos.
* Aparece una pista cerca del cursor con texto de UI, indicando qué sucederá si hacen clic.

Cuando usas el [**basado en System**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/system-based-events.md) método, puedes lograr los mismos resultados añadiendo un `PointerEvents` component a las entities clicables.

Tanto el resaltado de la Entity como la pista al pasar el cursor pueden desactivarse mediante propiedades en estos métodos y components.

También podrías implementar [pistas personalizadas avanzadas](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/system-based-events.md#advanced-custom-hints), por ejemplo, podrías reproducir un sonido, hacer que la Entity cambie de color, gire o se agrande mientras se le apunta, etc. Hagas lo que hagas, asegúrate de que sea un signo claro.

## Obstáculos

Los eventos de botón lanzan rays que solo interactúan con la primera Entity en su trayectoria que está suscrita a la pointer events collision layer. Esto es así siempre que la Entity esté dentro de sus límites de distancia. Si la Entity define límites de distancia tanto para la cámara como para el avatar, basta con que cualquiera de las dos esté lo suficientemente cerca.

Para que una Entity sea interceptada por el ray de un pointer event, debe:

* El modelo debe contener [mallas collider](/creator/content-creator-es/modelado-3d-y-animaciones/colliders.md).
* El `GltfContainer` debe estar configurado para usar la [geometría visible con máscaras de colisión](/creator/content-creator-es/escenas-sdk7/conceptos-basicos-de-contenido-3d/colliders.md#colliders-on-3d-models).
* La Entity debe tener un [componente MeshCollider](/creator/content-creator-es/escenas-sdk7/conceptos-basicos-de-contenido-3d/colliders.md).

Si el collider de otra Entity se interpone en el camino de la Entity con la que el player quiere interactuar, el player no podrá hacer clic en la Entity que está detrás, a menos que la Entity no tenga collider, o que este collider esté configurado para no responder a la pointer events collision layer.

```ts
// Entity clicable
const clickableEntity = engine.addEntity()
MeshRenderer.setBox(clickableEntity)
MeshCollider.setBox(clickableEntity)
Transform.create(clickableEntity, { position: Vector3.create(8, 1, 8) })

pointerEventsSystem.onPointerDown(
	{
		entity: clickableEntity,
		opts: {
			button: InputAction.IA_POINTER,
			hoverText: 'Click',
		},
	},
	function () {
		console.log('se hizo clic en la entidad')
		const t = Transform.getMutable(clickableEntity)
		t.scale.y += 0.2
	}
)

// no bloquea los clics
const nonBlocker = engine.addEntity()
MeshRenderer.setBox(nonBlocker)
MeshCollider.setBox(nonBlocker, ColliderLayer.CL_PHYSICS)
Transform.create(nonBlocker, { position: Vector3.create(10, 1, 8) })

// bloquea los clics
const blocker = engine.addEntity()
MeshRenderer.setBox(blocker)
MeshCollider.setBox(blocker, ColliderLayer.CL_POINTER)
Transform.create(blocker, { position: Vector3.create(8, 1, 10) })
```

{% hint style="warning" %}
**📔 Nota**: Para que una Entity no solo intercepte un pointer event, sino que también devuelva datos, la Entity también necesita tener un `PointerEvents` component. El `pointerEventsSystem` helpers también se encargan de este requisito.
{% endhint %}

## Botones del puntero

Las siguientes entradas pueden manejarse con cualquiera de los enfoques para detectar eventos de entrada.

* `InputAction.IA_POINTER`: **botón izquierdo del mouse** en una computadora, **botón de interacción** en mobile.
* `InputAction.IA_PRIMARY`: **E** tecla en una computadora, **botón E** en mobile.
* `InputAction.IA_SECONDARY`: **F** tecla en una computadora, **botón F** en mobile.
* `InputAction.IA_ACTION_3`: **1** tecla en una computadora, **botón 1** en mobile. *No es fácil de alcanzar en mobile — no se recomienda para interacción móvil.*
* `InputAction.IA_ACTION_4`: **2** tecla en una computadora, **botón 2** en mobile. *No es fácil de alcanzar en mobile — no se recomienda para interacción móvil.*
* `InputAction.IA_ACTION_5`: **3** tecla en una computadora, **botón 3** en mobile. *No es fácil de alcanzar en mobile — no se recomienda para interacción móvil.*
* `InputAction.IA_ACTION_6`: **4** tecla en una computadora, **botón 4** en mobile. *No es fácil de alcanzar en mobile — no se recomienda para interacción móvil.*
* `InputAction.IA_JUMP`: **Espacio** tecla en una computadora, **botón de salto** en mobile.
* `InputAction.IA_FORWARD`: **W** tecla en una computadora.
* `InputAction.IA_LEFT`: **Un** tecla en una computadora.
* `InputAction.IA_RIGHT`: **D** tecla en una computadora.
* `InputAction.IA_BACKWARD`: **S** tecla en una computadora.
* `InputAction.IA_WALK`: **Control** tecla en una computadora.
* `InputAction.IA_MODIFIER`: **Shift** tecla en una computadora.

Cada `InputAction` se abstrae de la entrada literal del teclado para que pueda mapearse a distintas entradas según el dispositivo. Por esta misma razón, no todos los botones del teclado pueden rastrearse para eventos de botón, solo los botones que se usan para movimiento e interacción. Esta limitación intencional garantiza que el contenido sea compatible entre desktop, la [client móvil](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/building-for-mobile.md), y futuros dispositivos como controladores de VR y otros mandos de juego.

{% hint style="warning" %}
**📱 Móvil**: En la [client móvil](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/building-for-mobile.md), todas las acciones de entrada están disponibles, pero `IA_ACTION_3`–`IA_ACTION_6` (los `1`/`2`/`3`/`4` botones) están ocultos detrás de un menú secundario y no son fáciles de alcanzar durante la partida. Al diseñar para mobile, prefiere `IA_POINTER` (botón de interacción), `IA_PRIMARY` (botón E), y `IA_SECONDARY` (botón F) para tus acciones clave. Consulta [Entrada en mobile](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/input-on-mobile.md).
{% endhint %}

## Tipos de eventos del pointer

Cada entrada puede producir los siguientes tipos de eventos del pointer. Cada uno de los siguientes es un valor en el `PointerEventType` .

* `PET_DOWN`: El player presiona un botón específico mientras tiene el cursor apuntando al collider de la Entity.
* `PET_UP`: El player suelta un botón específico mientras tiene el cursor apuntando al collider de la Entity.
* `PET_HOVER_ENTER`: El cursor del player empieza a apuntar al collider de la Entity.
* `PET_HOVER_LEAVE`: El cursor del player deja de apuntar al collider de la Entity.
* `PET_PROXIMITY_ENTER`: El player entra en el rango de proximidad de la Entity, sin importar hacia dónde esté mirando.
* `PET_PROXIMITY_LEAVE`: El player sale del rango de proximidad de la Entity.

Consulta [**Eventos de proximidad**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/proximity-events.md) para saber cómo usar interacciones basadas en proximidad.

## Datos de una acción de entrada

Todas las acciones de entrada incluyen datos sobre el evento, incluyendo cosas como el botón que se activó y hacia dónde apuntaba el pointer en ese momento.

Se puede obtener la siguiente información de cualquier evento de entrada:

* `analog`: Número opcional, solo presente en eventos de una entrada analógica (como un joystick), que almacena el valor analógico de la entrada.
* `button`: Qué id de botón se pulsó. El número corresponde a `InputAction` enum, que enumera todos los botones disponibles.
* `state`: Tipo de evento de puntero, del enum `PointerEventType`. *0* se refiere a `PointerEventType.PET_UP`, *1* en `PointerEventType.PET_DOWN`, *2* en `PointerEventType.PET_HOVER_ENTER`, *3* en `PointerEventType.PET_HOVER_LEAVE`, *4* en `PointerEventType.PET_PROXIMITY_ENTER`, *5* en `PointerEventType.PET_PROXIMITY_LEAVE`
* `timestamp`: Un [timestamp de Lamport](https://en.wikipedia.org/wiki/Lamport_timestamp) para identificar cada evento de botón.

  > Nota: Este timestamp no se numera según la hora actual. Piensa en él como un contador que empieza en 0 y se incrementa en 1 por cada evento.
* `hit`: Un objeto que contiene los siguientes datos sobre el evento de impacto:
  * `entityId`: Número de Id de la entidad que fue impactada por el rayo.
  * `meshName`: *String* con el nombre interno de la malla específica del modelo 3D que fue impactada. Esto es útil cuando un modelo 3D está compuesto por múltiples mallas.
  * `globalOrigin`: *Vector3* para la posición donde se origina el rayo (relativa a la escena)
  * `direction`: *Vector3* con el vector de dirección del rayo, en coordenadas globales
  * `posición`: *Vector3* para la posición donde el rayo intersectó con la entidad impactada (relativa a la escena)
  * `length`: Longitud del rayo desde su origen hasta la posición donde ocurrió el impacto contra la entidad.
  * `normalHit`: *Vector3* con un vector de dirección normalizado, que describe el ángulo de la normal del impacto en el espacio global.

Se accede a estos datos de distintas maneras según el enfoque que estés usando para manejar las acciones de entrada.

Usando el [**Registrar un callback**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/register-callback.md) enfoque, el primer parámetro que se pasa a la función callback contiene toda esta estructura de datos.

```ts
pointerEventsSystem.onPointerDown({ entity: myEntity }, function (cmd) {
	console.log(cmd.hit?.entityId)
})
```

Usando el [**basado en System**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/system-based-events.md) enfoque, usa `inputSystem.getInputCommand()` para obtener estos datos.

```ts
engine.addSystem(() => {
	const cmd = inputSystem.getInputCommand(
		InputAction.IA_POINTER,
		PointerEventType.PET_DOWN,
		myEntity
	)
	if (cmd) {
		console.log(cmd.hit?.entityId)
	}
})
```

{% hint style="warning" %}
**📔 Nota**: Para que una Entity no solo intercepte un pointer event, sino que también devuelva datos, la Entity también necesita tener un `PointerEvents` component. El `pointerEventsSystem` helpers también se encargan de este requisito.
{% endhint %}

Usando el [**Avanzado**](/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/advanced-button-events.md) enfoque, el `PointerEventsResult` contiene una lista con un historial reciente de todos los pointer events contra esa Entity.

```ts
engine.addSystem(() => {
	for (const [entity] of engine.getEntitiesWith(PointerEventsResult)) {
		const pointerEvents = PointerEventsResult.get(entity)

		for (const event of pointerEvents) {
			console.log(event.hit?.entityId)
		}
	}
})
```

## Bloquear o desbloquear el cursor

{% hint style="info" %}
**💡 Nota**: `PointerLock` es un concepto del cliente de escritorio (cursor del mouse bloqueado vs. desbloqueado). No tiene efecto en la [aplicación móvil](/creator/content-creator-es/escenas-sdk7/desarrollar-para-movil/building-for-mobile.md), donde la entrada se basa en el tacto.
{% endhint %}

Los players en el cliente de escritorio de Decentraland pueden alternar entre dos modos de interacción distintos con su cursor:

* Cursor bloqueado: mover el mouse desplaza la cámara y los eventos de clic ocurren en la mira en el centro de la pantalla
* Cursor desbloqueado: el cursor puede moverse libremente independientemente de la cámara, y los players pueden hacer clic en cualquier lugar de la pantalla para interactuar con el espacio 3D o con la UI

Estos modos de interacción son ideales para distintos tipos de mecánicas de juego, y quizás quieras hacer que los players adopten uno u otro según lo que mejor se adapte a tu escena. También puedes querer asegurarte momentáneamente de que el cursor del player esté desbloqueado para permitirle interactuar con una UI; esto es especialmente útil para los nuevos players que no están familiarizados con cómo se controla esto.

Para cambiar el estado del cursor del player, usa el `PointerLock` component en el `engine.CameraEntity` entidad.

```ts
import {PointerLock} from '@dcl/sdk/ecs'
    
PointerLock.createOrReplace(engine.CameraEntity, {isPointerLocked: false})
```

{% hint style="warning" %}
**📔 Nota**: El engine proporciona un `PointerLock` component en el `engine.CameraEntity` por defecto. Usa `createOrReplace()` o `getMutable()` en lugar de `create()`, que lanza un error si el component ya existe.
{% endhint %}

También puedes consultar el estado del cursor del player leyendo el `PointerLock` estado del component.

```ts
import {PointerLock} from '@dcl/sdk/ecs'

const isPointerLocked = PointerLock.getOrNull(engine.CameraEntity)?.isPointerLocked
```

Usa la `.onChange` function para reaccionar a cambios en el estado del pointer. El siguiente ejemplo impone que el cursor esté siempre desbloqueado.

```ts
import {PointerLock} from '@dcl/sdk/ecs'

export function main() {

    PointerLock.createOrReplace(engine.CameraEntity, {isPointerLocked: false});

    PointerLock.onChange(engine.CameraEntity, (pointerLock) => {
		    if (!pointerLock) return
		    if(pointerLock.isPointerLocked){
			    PointerLock.getMutable(engine.CameraEntity).isPointerLocked = false
		   }
	})
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.decentraland.org/creator/content-creator-es/escenas-sdk7/interactividad/eventos-de-boton/click-events.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
