> 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/scenes-sdk7/interactividad/eventos-de-boton/click-events.md).

# Eventos de Click

Una escena de Decentraland puede detectar acciones de entrada de todos los botones que se usan para controlar el avatar del jugador. Estas incluyen clics del puntero, 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 un teclado en el cliente de escritorio, de los controles en pantalla en la [mobile app](/creator/content-creator-es/scenes-sdk7/creacion-para-moviles/building-for-mobile.md), de un controlador VR, o de otros dispositivos de entrada — el SDK interpreta todo esto de la misma manera.

Puedes detectar acciones de entrada sobre una Entity. Esto implica presionar un botón mientras el cursor del jugador apunta al collider de esa Entity. También puedes detectar *global* evento de entrada, que implica activar la entrada en cualquier momento, sin considerar hacia dónde apunta el pointer.

{% hint style="warning" %}
**📔 Nota**: Las Entities deben tener un [collider](/creator/content-creator-es/scenes-sdk7/conceptos-basicos-de-contenido-3d/colliders.md) para responder a las acciones de entrada. `MeshRenderer` los models también deben recibir un `MeshCollider` component. Los models 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 añadir un `MeshCollider` component.
{% endhint %}

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

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

## Usa el 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 modo sin código **On Click** o **On Input Action** Triggers en un item para llamar acciones al hacer clic sobre él. O usa **On Global Click**, **On Global Primary** o **On Global Secondary** Triggers para reaccionar a eventos globales de botones. Ver [Convierte cualquier item en smart](/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: 'Click' },
	},
	function () {
		console.log('clicked entity')
	}
)
```

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

## Feedback al Hover

Es importante hacer que los jugadores sepan que una Entity es interactiva. De lo contrario, podrían perderse por completo la experiencia que construiste. No es una buena experiencia hacer clic en todos los objetos esperando que uno responda.

Cuando usas el [**Registrar un callback**](/creator/content-creator-es/scenes-sdk7/interactividad/eventos-de-boton/register-callback.md) método, se muestran dos tipos de feedback cada vez que el jugador 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 como para hacer clic, y rojo si la Entity está demasiado lejos.
* Aparece una hint de Hover cerca del cursor con texto de UI, indicando qué sucederá si hace clic.

Al usar el [**Basado en System**](/creator/content-creator-es/scenes-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 hint de Hover pueden desactivarse mediante propiedades en estos métodos y components.

También podrías implementar [hints personalizados avanzados](/creator/content-creator-es/scenes-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 aumente de tamaño mientras se le apunta, etc. Hagas lo que hagas, asegúrate de que sea un signifier 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 collision layer de pointer events. Esto es cierto siempre que la Entity esté más cerca que sus límites de distancia tanto del avatar como de la cámara.

Para que una Entity sea interceptada por el ray de un evento de pointer, debe cumplirse una de estas condiciones:

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

Si el collider de otra Entity está en medio de la Entity con la que el jugador quiere interactuar, el jugador 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 collision layer de pointer events.

```ts
// entidad 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('clicked entity')
		const t = Transform.getMutable(clickableEntity)
		t.scale.y += 0.2
	}
)

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

// bloqueador para 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 evento de pointer, sino que también devuelva datos, la Entity también necesita tener un `PointerEvents` component. Los helpers de `pointerEventsSystem` también se encargan de este requisito.
{% endhint %}

## Botones del puntero

Las siguientes entradas pueden ser manejadas por 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 móvil.
* `InputAction.IA_PRIMARY`: **E** tecla en una computadora, **Botón E** en móvil.
* `InputAction.IA_SECONDARY`: **F** tecla en una computadora, **Botón F** en móvil.
* `InputAction.IA_ACTION_3`: **1** tecla en una computadora, **botón 1** en móvil. *No es de fácil acceso en móvil — no se recomienda para la interacción en móvil.*
* `InputAction.IA_ACTION_4`: **2** tecla en una computadora, **botón 2** en móvil. *No es de fácil acceso en móvil — no se recomienda para la interacción en móvil.*
* `InputAction.IA_ACTION_5`: **3** tecla en una computadora, **botón 3** en móvil. *No es de fácil acceso en móvil — no se recomienda para la interacción en móvil.*
* `InputAction.IA_ACTION_6`: **4** tecla en una computadora, **botón 4** en móvil. *No es de fácil acceso en móvil — no se recomienda para la interacción en móvil.*
* `InputAction.IA_JUMP`: **Space** tecla en una computadora, **botón de salto** en móvil.
* `InputAction.IA_FORWARD`: **W** tecla en una computadora.
* `InputAction.IA_LEFT`: **A** 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 en el teclado para que pueda asignarse a diferentes 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 asegura que el contenido sea compatible entre desktop, el [cliente móvil](/creator/content-creator-es/scenes-sdk7/creacion-para-moviles/building-for-mobile.md)y dispositivos futuros como controladores VR y otros game controllers.

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

## Tipos de eventos de pointer

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

* `DOWN`: El jugador presiona un botón específico mientras tiene el cursor apuntando al collider de la Entity.
* `UP`: El jugador suelta un botón específico mientras tiene el cursor apuntando al collider de la Entity.
* `HOVER_ENTER`: El cursor del jugador comienza a apuntar al collider de la Entity.
* `HOVER_LEAVE`: El cursor del jugador deja de apuntar al collider de la Entity.
* `PROXIMITY_ENTER`: El jugador entra dentro del rango de proximidad de la Entity, sin importar hacia dónde esté mirando.
* `PROXIMITY_LEAVE`: El jugador sale del rango de proximidad de la Entity.

Consulta [**Proximity Events**](/creator/content-creator-es/scenes-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, 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`: Marca para indicar si el evento proviene de una entrada analógica o digital. Las entradas digitales tienen un valor de *1*, las entradas analógicas (como un joystick) tienen un valor de *0*.
* `button`: Qué id de botón fue presionado. El número corresponde al `InputAction` enum, que lista todos los botones disponibles.
* `state`: Tipo de evento de pointer, del enum `PointerEventType`. *0* se refiere a `PointerEventType.PET_DOWN`, *1* a `PointerEventType.PET_UP`, *2* a `PointerEventType.PET_HOVER_ENTER`, *3* a `PointerEventType.PET_HOVER_LEAVE`
* `timestamp`: Un [timestamp de Lamport](https://en.wikipedia.org/wiki/Lamport_timestamp) para identificar cada evento de botón.

  > Nota: Este timestamp no está numerado según la hora actual. Piensa en él como un contador que comienza en 0 y se incrementa en 1 por cada evento.
* `hit`: Un objeto que contiene los siguientes datos sobre el evento de hit:
  * `entityId`: Número de id de la Entity que fue alcanzada por el ray.
  * `meshName`: *String* con el nombre interno del mesh específico del model 3D que fue golpeado. Esto es útil cuando un model 3D está compuesto por múltiples meshes.
  * `origin`: *Vector3* para la posición desde donde se origina el ray (relativa a la scene)
  * `position`: *Vector3* para la posición donde el ray intersectó con la Entity golpeada (relativa a la scene)
  * `length`: Longitud del ray desde su origen hasta la posición donde ocurrió el hit contra la Entity.
  * `normalHit`: *Quaternion* para el ángulo de la normal del hit en world space.

Estos datos se acceden de distintas maneras según el enfoque que estés usando para manejar acciones de entrada.

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

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

Al usar el [**Basado en System**](/creator/content-creator-es/scenes-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 evento de pointer, sino que también devuelva datos, la Entity también necesita tener un `PointerEvents` component. Los helpers de `pointerEventsSystem` también se encargan de este requisito.
{% endhint %}

Al usar el [**Avanzado**](/creator/content-creator-es/scenes-sdk7/interactividad/eventos-de-boton/advanced-button-events.md) enfoque, el `PointerEventsResults` contiene un array con un historial reciente de todos los eventos de pointer contra esa Entity.

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

		if (poninterEvents.commands.length > 0) {
			console.log(poninterEvents.commands[0].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 [mobile app](/creator/content-creator-es/scenes-sdk7/creacion-para-moviles/building-for-mobile.md), donde la entrada es táctil.
{% endhint %}

Los jugadores 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 es libre de moverse independientemente de la cámara, y los jugadores pueden hacer clic en cualquier parte 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 puede que quieras hacer que los jugadores adopten uno u otro según lo que mejor se adapte a tu scene. También puede que quieras asegurarte momentáneamente de que el cursor del jugador esté desbloqueado para permitirle interactuar con una UI; esto es especialmente útil para jugadores nuevos que no están familiarizados con cómo se controla esto.

Para cambiar el estado del cursor del jugador, usa el `PointerLock` component en la `engine.CameraEntity` entity.

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

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

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

PointerLock.create(engine.CameraEntity)

const isPointerLocked = PointerLock.get(engine.CameraEntity).isPointerLocked
```

Usa la función `.onChange` para reaccionar a cambios en el estado del pointer. El siguiente ejemplo fuerza que el cursor esté siempre desbloqueado.

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

export function main() {

    PointerLock.create(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/scenes-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.
