> 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-pt/scenes-sdk7/interatividade/player-physics.md).

# Física do Player

Aplique forças e impulsos ao avatar do jogador

Podes aplicar forças físicas ao avatar do jogador a partir do código da tua Scene. Isto permite-te criar mecânicas de gameplay como plataformas de lançamento, zonas de vento, efeitos de recuo, explosões e muito mais.

Há dois tipos de força que podes aplicar:

* **Impulso**: Um empurrão instantâneo de uma só vez. Usa isto para efeitos discretos e súbitos, como lançar o jogador no ar ou fazê-lo recuar.
* **Força contínua**: Um empurrão sustentado aplicado a cada tick enquanto estiver ativo. Usa isto para efeitos contínuos como zonas de vento, correntes de água ou campos gravitacionais.

Ambos são aplicados através do `Physics` helper, importado de `@dcl/sdk/ecs`.

{% hint style="warning" %}
**📔 Observação**: Estas forças afetam apenas o avatar do jogador local. Os outros jogadores veem as alterações nas posições dos outros jogadores, mas as forças em si não são sincronizadas com outros jogadores no multiplayer. A física de cada jogador corre localmente na sua própria instância.
{% endhint %}

## Aplica um impulso

Use `Physics.applyImpulseToPlayer()` para dar ao jogador um empurrão de uma só vez numa dada direção.

* `vetor`: Direção e força combinadas — o comprimento do vetor codifica a magnitude do impulso.

```ts
import { Physics } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

// Lança o jogador diretamente para cima
Physics.applyImpulseToPlayer(Vector3.create(0, 50, 0))
```

Também podes passar uma direção e uma magnitude separadamente. Neste caso, o vetor de direção é normalizado automaticamente:

* `direção`: Direção para empurrar — normalizada automaticamente antes do escalonamento.
* `magnitude`: Força do impulso.

```ts
import { Physics } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

// Lança o jogador para cima com uma magnitude de 50
Physics.applyImpulseToPlayer(Vector3.create(0, 1, 0), 50)
```

Se chamares `applyImpulseToPlayer()` várias vezes dentro da mesma frame, os impulsos são acumulados — são somados e aplicados como um único impulso combinado.

### Acionar um impulso na entrada do jogador

Um padrão comum é acionar um impulso quando o jogador entra numa área. Usa uma área de trigger para detetar quando o jogador entra:

```ts
import { engine, Physics, TriggerArea, triggerAreaEventsSystem, ColliderLayer, MeshRenderer, Transform } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

const launchPad = engine.addEntity()
Transform.create(launchPad, { position: Vector3.create(8, 0, 8) })
MeshRenderer.setBox(launchPad)
TriggerArea.setBox(launchPad, ColliderLayer.CL_PLAYER)

triggerAreaEventsSystem.onTriggerEnter(launchPad, (result) => {
	if (result.trigger?.entity !== engine.PlayerEntity) return
	Physics.applyImpulseToPlayer(Vector3.create(0, 50, 0))
})
```

## Aplicar um impulso de recuo

Use `Physics.applyKnockbackToPlayer()` para empurrar o jogador para longe de um ponto com um único impulso. Isto é ideal para explosões, efeitos de impacto e outras rajadas direcionais de uma só vez. A direção é calculada automaticamente a partir do ponto de origem até à posição atual do jogador.

```ts
import { Physics } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

const explosionPosition = Vector3.create(8, 1, 8)

// Afasta o jogador do centro da explosão
Physics.applyKnockbackToPlayer(explosionPosition, 40)
```

Podes limitar a área de efeito com um `raio`, e controlar como a magnitude diminui com a distância usando a opção `KnockbackFalloff` :

* `fromPosition`: Origem em world-space do recuo (centro da explosão, posição do inimigo, etc.).
* `magnitude`: Força base do impulso.
* `raio`: Distância máxima de efeito (predefinição: `Infinity`).
* `falloff`: Como a magnitude diminui com a distância (predefinição: `CONSTANT`).

```ts
import { Physics, KnockbackFalloff } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

Physics.applyKnockbackToPlayer(
	Vector3.create(8, 1, 8),
	40,                          // magnitude
	10,                          // radius: sem efeito além de 10 metros
	KnockbackFalloff.LINEAR      // magnitude esbate-se até 0 na extremidade do raio
)
```

O `KnockbackFalloff` enum controla como a força diminui com a distância:

* `KnockbackFalloff.CONSTANT` — mesma magnitude a qualquer distância dentro do raio (predefinição)
* `KnockbackFalloff.LINEAR` — diminuição linear suave até 0 na extremidade do raio
* `KnockbackFalloff.INVERSE_SQUARE` — queda acentuada e fisicamente realista

Se o jogador estiver exatamente na posição de origem, o jogador é empurrado diretamente para cima. Uma magnitude negativa puxa o jogador em direção ao ponto em vez de o afastar.

Os mesmos `KnockbackFalloff` valores estão disponíveis para `applyRepulsionForceToPlayer()`.

## Aplicar uma força contínua

Use `Physics.applyForceToPlayer()` para aplicar uma força sustentada ao jogador. Ao contrário de um impulso, esta força é aplicada a cada tick enquanto permanecer ativa.

* `fonte`: Uma entidade que identifica esta fonte de força — usa-a para atualizar ou remover a força mais tarde.
* `vetor`: Direção e força combinadas — o comprimento do vetor codifica a magnitude da força.

A posição da entidade de origem não é relevante — é usada apenas como identificador.

```ts
import { engine, Physics } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

const windZoneEntity = engine.addEntity()

// Empurra o jogador para a direita continuamente
Physics.applyForceToPlayer(windZoneEntity, Vector3.create(10, 0, 0))
```

O vetor de força está sempre em **world space**. Se precisares de uma direção relativa a uma entidade rodada, usa `Transform.localToWorldDirection()` para o converter primeiro — vê [Converter uma direção local para world space](#convert-a-local-direction-to-world-space).

Tal como com `applyImpulseToPlayer()`, também podes passar `direção` e `magnitude` separadamente — vê [Aplica um impulso](#apply-an-impulse):

```ts
Physics.applyForceToPlayer(windZoneEntity, Vector3.create(0, 1, 0), 50)
```

Se chamares `applyForceToPlayer()` novamente com a mesma entidade de origem, substitui a força anterior dessa origem. Se várias fontes de força forem acumuladas, os seus vetores são somados a cada tick.

### Remover uma força contínua

Para parar de aplicar uma força, chama `Physics.removeForceFromPlayer()` com uma referência para a entidade de origem que foi usada para criar a força. Se a entidade não estiver atualmente a aplicar uma força, esta chamada é ignorada em segurança.

* `fonte`: A entidade usada quando a força foi aplicada.

```ts
Physics.removeForceFromPlayer(windZoneEntity)
```

### Aplicar uma força por uma duração limitada

Use `Physics.applyForceToPlayerForDuration()` para aplicar uma força durante uma quantidade específica de tempo. A duração é em segundos. A força é removida automaticamente quando o tempo termina. Chamar isto novamente com a mesma entidade de origem reinicia o temporizador.

* `fonte`: Uma entidade que identifica esta fonte de força.
* `duration`: Quanto tempo a força dura, em segundos.
* `vetor`: Direção e força combinadas — o comprimento do vetor codifica a magnitude da força.

```ts
import { engine, Physics } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

const gustEntity = engine.addEntity()

// Aplica uma forte força ascendente durante 1,5 segundos
Physics.applyForceToPlayerForDuration(gustEntity, 1.5, Vector3.create(0, 50, 0))
```

O `direção` + `magnitude` overload também está disponível — vê [Aplica um impulso](#apply-an-impulse):

```ts
Physics.applyForceToPlayerForDuration(gustEntity, 1.5, Vector3.create(0, 1, 0), 50)
```

### Exemplo de zona de vento

Este exemplo cria um túnel de vento que empurra o jogador enquanto ele está dentro dele, e para quando ele sai:

```ts
import { engine, Physics, TriggerArea, triggerAreaEventsSystem, ColliderLayer, MeshRenderer, MeshCollider, Transform } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

const windTunnel = engine.addEntity()
Transform.create(windTunnel, {
	position: Vector3.create(8, 1, 8),
	scale: Vector3.create(4, 3, 4),
})
MeshRenderer.setBox(windTunnel)
TriggerArea.setBox(windTunnel, ColliderLayer.CL_PLAYER)

triggerAreaEventsSystem.onTriggerEnter(windTunnel, (result) => {
	if (result.trigger?.entity !== engine.PlayerEntity) return
	Physics.applyForceToPlayer(windTunnel, Vector3.create(15, 0, 0))  // empurra lateralmente ao longo do eixo X
})

triggerAreaEventsSystem.onTriggerExit(windTunnel, (result) => {
	if (result.trigger?.entity !== engine.PlayerEntity) return
	Physics.removeForceFromPlayer(windTunnel)
})
```

## Aplicar uma força de repulsão

Use `Physics.applyRepulsionForceToPlayer()` para empurrar continuamente o jogador para longe de um ponto fixo no espaço. Isto é adequado para efeitos como um campo de repulsão magnética, uma barreira de força ou um objeto flutuante que mantém os jogadores à distância. Ao contrário de `applyKnockbackToPlayer()`, esta força é recalculada a cada tick à medida que o jogador se move. A magnitude enfraquece com a distância com base no raio e no falloff — vê [Aplicar um impulso de recuo](#apply-a-knockback-impulse) para as `KnockbackFalloff` opções. Uma magnitude negativa inverte o efeito, puxando continuamente o jogador em direção ao ponto como um vórtice ou poço gravitacional.

{% hint style="warning" %}
**📔 Observação**: A origem da repulsão é o `fromPosition` vetor que passas — **não** a posição da `fonte` entidade. A `fonte` entidade é usada apenas como identificador para poderes atualizar ou remover a força mais tarde. A sua posição, rotação e escala são completamente ignoradas.
{% endhint %}

* `fonte`: Uma entidade usada como identificador para esta força — a sua posição não é usada.
* `fromPosition`: O ponto em world-space de onde o jogador é afastado.
* `magnitude`: Força base. Valores negativos atraem em vez de repelir.
* `raio`: Distância máxima de efeito (predefinição: `Infinity`).
* `falloff`: Como a magnitude diminui com a distância (predefinição: `CONSTANT`).

```ts
import { engine, Physics, Transform, timers } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

const repulsionSource = engine.addEntity()
Transform.create(repulsionSource, { position: Vector3.create(8, 1, 8) })

// Passa explicitamente a posição da entidade como origem da repulsão
Physics.applyRepulsionForceToPlayer(
	repulsionSource,
	Transform.get(repulsionSource).position,  // origem da repulsão — passada explicitamente, não lida automaticamente
	50,                                         // magnitude
	10,                                         // raio de efeito em metros
)

// Remove a força após meio segundo
timers.setTimeout(() => {
    Physics.removeForceFromPlayer(repulsionSource)
}, 500)
```

## Forças enquanto desliza

Enquanto o jogador está a deslizar, as forças contínuas comportam-se de forma diferente:

* Forças contínuas — de `applyForceToPlayer()`, `applyForceToPlayerForDuration()`, ou `applyRepulsionForceToPlayer()` — são **1,5 vezes mais fortes**, uma vez que o planador aberto apanha o fluxo de ar. Zonas de vento e correntes parecem mais responsivas para um jogador a deslizar.
* O componente ascendente de uma força contínua pode **elevar** um jogador a deslizar. O limite de velocidade de queda do planador apenas limita o quão depressa o jogador desce; não cancela o movimento ascendente, por isso uma corrente de vento inclinada ou vertical empurra o jogador ao longo de toda a direção da força.

Impulsos de uma só vez — de `applyImpulseToPlayer()` ou `applyKnockbackToPlayer()` — não são afetados pelo deslizar. Comportam-se da mesma forma quer o planador esteja aberto quer fechado.

Podes combinar estes comportamentos para construir mecânicas como correntes térmicas ascendentes que levam jogadores a deslizar para cima, ou corredores de vento que são mais fáceis de atravessar com o planador aberto. Para ajustar a velocidade de queda ou a velocidade para a frente do planador, usa o `AvatarLocomotionSettings` component, vê [Definições de Locomotion](/creator/content-creator-pt/scenes-sdk7/interatividade/avatares/locomotion.md#locomotion-settings).

## Converter uma direção local para world space

Use `Transform.localToWorldDirection()` para transformar um vetor de direção do espaço local de uma entidade para world space, tendo em conta toda a hierarquia de pais. Isto é útil ao aplicar forças relativas a uma entidade rodada — por exemplo, empurrar o jogador para longe de uma face específica de um obstáculo em rotação.

* `entity`: A entidade de origem cujo espaço local define a direção.
* `localDirection`: Vetor de direção nas coordenadas locais da entidade.

Devolve o vetor de direção em coordenadas de world.

Isto aplica **apenas rotação** — não tem em conta translação nem escala — tornando-o diretamente adequado para vetores de direção passados a funções de força e impulso.

```ts
import { Physics, Transform } from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

// Empurra o jogador na direção para onde aponta o eixo local +Z da entidade em world space
const worldDir = Transform.localToWorldDirection(myEntity, Vector3.create(0, 0, 1))
Physics.applyImpulseToPlayer(worldDir, 20)
```


---

# 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-pt/scenes-sdk7/interatividade/player-physics.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.
