> 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-button/click-events.md).

# Eventos de clic

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

Una escena de Decentraland puede detectar acciones de entrada de todos los botones que se usan para controlar el avatar del jugador. Estos 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 provenir de un mouse y teclado en el cliente de escritorio, de los controles en pantalla en el [aplicación móvil](/creator/content-creator-es/desarrollar-para-movil/cliente-movil/overview.md), de un controlador VR o de otros dispositivos de entrada — el SDK los interpreta todos igual.

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

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

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

* [**Registrar un callback**](/creator/content-creator-es/scenes-sdk7/interactividad/eventos-de-button/register-callback.md): La forma más fácil de agregar interacción a una sola entidad. Escribe una sola sentencia para configurar una función de callback y feedback al pasar el cursor.
* [**basado en System**](/creator/content-creator-es/scenes-sdk7/interactividad/eventos-de-button/system-based-events.md): Ideal para manejar múltiples entidades con comportamiento similar. Usa un system para iterar sobre entidades similares y consultar acciones de entrada en cada una, manejándolas todas con la misma lógica. El feedback 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/scenes-sdk7/interactividad/eventos-de-button/advanced-button-events.md): Lee los datos de respuesta sin procesar en cada entidad, incluidas las 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 fácil de manejar eventos de clic en una entidad es usar el Scene Editor. Usa el no-code **On Click** o **Al realizar una acción de entrada** Triggers en un elemento para llamar acciones al hacer clic en él. O usa **Clic global**, **Primario global** o **Secundario global** Triggers para reaccionar a eventos globales de botón. Consulta [Convierte cualquier item en smart](/creator/content-creator-es/scene-editor/interactividad/make-any-item-smart.md).

## Ejemplo simple

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

```ts
pointerEventsSystem.onPointerDown(
	{
		entity: myEntity,
		opts: { button: InputAction.IA_PRIMARY, hoverText: 'Clic' },
	},
	function () {
		console.log('Entity pulsada')
	}
)
```

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

## Feedback al pasar el cursor

Es importante hacer que los jugadores sepan que una entidad 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-button/register-callback.md) método, se muestran dos tipos de feedback cada vez que el jugador pasa su cursor sobre el objeto:

* El borde de la entidad se resalta (solo en el cliente de escritorio de Decentraland 2.0). El resaltado es verde si la entidad está lo suficientemente cerca para hacer clic, rojo si la entidad está demasiado lejos.
* Aparece una pista al pasar el cursor cerca, con texto de UI, que señala lo que sucederá si hacen clic.

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

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

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

## Obstáculos

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

Para que una entidad sea interceptada por el rayo de un pointer event, debe cumplirse una de estas condiciones:

* El modelo debe contener [mallas collider](/creator/content-creator-es/modelado-y-animaciones-3d/colliders.md).
* El `GltfContainer` debe configurarse para usar la [geometría visible con máscaras de colisión](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/colliders.md#colliders-on-3d-models).
* La entidad debe tener un [MeshCollider component](/creator/content-creator-es/scenes-sdk7/fundamentos-del-contenido-3d/colliders.md).

Si el collider de otra entidad se interpone en el camino de la entidad con la que el jugador quiere interactuar, el jugador no podrá hacer clic en la entidad que está detrás, a menos que la entidad no tenga collider, o que este collider esté configurado para no responder a la capa de colisión 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('Entity pulsada')
		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 entidad no solo intercepte un pointer event, sino que también devuelva datos, la entidad 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 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 fácil de alcanzar en móvil — no se recomienda para interacción móvil.*
* `InputAction.IA_ACTION_4`: **2** tecla en una computadora, **botón 2** en móvil. *No es fácil de alcanzar en móvil — no se recomienda para interacción móvil.*
* `InputAction.IA_ACTION_5`: **3** tecla en una computadora, **botón 3** en móvil. *No es fácil de alcanzar en móvil — no se recomienda para interacción móvil.*
* `InputAction.IA_ACTION_6`: **4** tecla en una computadora, **botón 4** en móvil. *No es fácil de alcanzar en móvil — no se recomienda para interacción 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`: **Un** tecla en una computadora.
* `InputAction.IA_RIGHT`: **D** tecla en una computadora.
* `InputAction.IA_BACKWARD`: **S** tecla en una computadora.
* `InputAction.IA_WALK`: **Controlar** 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 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 el movimiento y la interacción. Esta limitación intencional garantiza que el contenido sea compatible en desktop, el [cliente móvil](/creator/content-creator-es/desarrollar-para-movil/cliente-movil/overview.md)y futuros dispositivos como controladores VR y otros mandos de juego.

{% hint style="warning" %}
**📱 Móvil**: En el [cliente móvil](/creator/content-creator-es/desarrollar-para-movil/cliente-movil/overview.md), todas las acciones de entrada están disponibles, pero `IA_ACTION_3`–`IA_ACTION_6` (la `1`/`2`/`3`/`4` los botones) están ocultos detrás de un menú secundario y no son fáciles de alcanzar durante el juego. 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. Consulta [Entrada en móvil](/creator/content-creator-es/desarrollar-para-movil/desarrollar/input-on-mobile.md).
{% endhint %}

## Tipos de eventos de puntero

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

* `PET_DOWN`: El jugador presiona un botón específico mientras el cursor apunta al collider de la entidad.
* `PET_UP`: El jugador suelta un botón específico mientras el cursor apunta al collider de la entidad.
* `PET_HOVER_ENTER`: El cursor del jugador empieza a apuntar al collider de la entidad.
* `PET_HOVER_LEAVE`: El cursor del jugador deja de apuntar al collider de la entidad.
* `PET_PROXIMITY_ENTER`: El jugador entra en el rango de proximidad de la entidad, sin importar hacia dónde mire.
* `PET_PROXIMITY_LEAVE`: El jugador sale del rango de proximidad de la entidad.

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

## Datos de una acción de entrada

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

La siguiente información puede obtenerse de cualquier evento de entrada:

* `analog`: Número opcional, presente solo en eventos de una entrada analógica (como un joystick), que almacena el valor analógico de la entrada.
* `botón`: Qué id de botón se pulsó. El número corresponde al `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`
* `marca de tiempo`: Un [marca de tiempo de Lamport](https://en.wikipedia.org/wiki/Lamport_timestamp) para identificar cada evento de botón.

  > Nota: Esta marca de tiempo no está numerada en función de la hora actual. Piénsalo como un contador que empieza en 0 y se incrementa en 1 por cada evento.
* `impacto`: Un objeto que contiene los siguientes datos sobre el evento de impacto:
  * `entityId`: Número de Id de la Entity 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)
  * `dirección`: *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 Entity impactada (relativa a la escena)
  * `length`: Longitud del rayo desde su origen hasta la posición donde ocurrió el impacto contra la Entity.
  * `normalHit`: *Vector3* con un vector de dirección normalizado, que describe el ángulo de la normal del impacto en el espacio mundial.

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

Usando el [**Registrar un callback**](/creator/content-creator-es/scenes-sdk7/interactividad/eventos-de-button/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)
})
```

Usando el [**basado en System**](/creator/content-creator-es/scenes-sdk7/interactividad/eventos-de-button/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 entidad no solo intercepte un pointer event, sino que también devuelva datos, la entidad 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/scenes-sdk7/interactividad/eventos-de-button/advanced-button-events.md) enfoque, el `PointerEventsResult` contiene una lista con un historial reciente de todos los pointer events de esa entidad.

```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 el [aplicación móvil](/creator/content-creator-es/desarrollar-para-movil/cliente-movil/overview.md), donde la entrada se basa en el tacto.
{% endhint %}

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

* Cursor bloqueado: al mover el mouse, la cámara se desplaza y los eventos de clic ocurren en la mira en el centro de la pantalla
* Cursor desbloqueado: el cursor puede moverse libremente de forma independiente a la cámara, y los jugadores pueden hacer clic en cualquier parte de la pantalla para interactuar con el espacio 3D o 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 escena. 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 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 jugador leyendo el `PointerLock` estado del component.

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

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

Usa el `.onChange` función para reaccionar a cambios en el estado del puntero. 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
