> 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).

# Physics do Player

Aplique forças e impulses ao avatar do player

Você pode aplicar forças físicas ao avatar do jogador a partir do código da sua cena. Isso permite criar mecânicas de gameplay como plataformas de lançamento, zonas de vento, efeitos de knockback, explosões e muito mais.

Há dois tipos de força que você pode aplicar:

* **Impulso**: Um empurrão instantâneo de uso único. Use isto para efeitos discretos e súbitos, como lançar o jogador para o ar ou afastá-lo.
* **Força contínua**: Um empurrão sustentado aplicado a cada tick enquanto estiver ativo. Use 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" %}
**📔 Nota**: Essas forças afetam apenas o avatar do jogador local. Os outros jogadores veem as mudanças nas posições dos demais jogadores, mas as forças em si não são sincronizadas com os outros jogadores no multiplayer. A física de cada jogador é executada localmente em sua própria instância.
{% endhint %}

## Aplicar um impulso

Use `Physics.applyImpulseToPlayer()` para dar ao jogador um empurrão único em uma determinada 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çar o jogador diretamente para cima
Physics.applyImpulseToPlayer(Vector3.create(0, 50, 0))
```

Você também pode passar uma direção e uma magnitude separadamente. Neste caso, o vetor de direção é normalizado automaticamente:

* `direção`: Direção do empurrão — normalizada automaticamente antes da escala.
* `magnitude`: Força do impulso.

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

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

Se você chamar `applyImpulseToPlayer()` várias vezes dentro do mesmo frame, os impulsos são acumulados — eles são somados e aplicados como um único impulso combinado.

### Disparar um impulso na entrada do jogador

Um padrão comum é disparar um impulso quando o jogador entra em uma área. Use uma trigger area para detectar 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 knockback

Use `Physics.applyKnockbackToPlayer()` para afastar o jogador de um ponto com um único impulso. Isso é ideal para explosões, efeitos de impacto e outros disparos direcionais de uso único. A direção é calculada automaticamente do ponto de origem até a 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)

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

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

* `fromPosition`: Origem no espaço global do knockback (centro da explosão, posição do inimigo, etc.).
* `magnitude`: Força base do impulso.
* `raio`: Distância máxima de efeito (padrão: `Infinity`).
* `falloff`: Como a magnitude diminui com a distância (padrã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,                          // raio: sem efeito além de 10 metros
	KnockbackFalloff.LINEAR      // a magnitude cai até 0 na borda do raio
)
```

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

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

Se o jogador estiver exatamente na posição da origem, ele será empurrado diretamente para cima. Uma magnitude negativa puxa o jogador em direção ao ponto em vez de afastá-lo.

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. Diferente de um impulso, essa força é aplicada a cada tick enquanto permanecer ativa.

* `source`: Uma entity que identifica a origem dessa força — use-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 entity de origem não é relevante — ela é usada apenas como identificador.

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

const windZoneEntity = engine.addEntity()

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

O vetor de força está sempre em **world space**. Se você precisar de uma direção relativa a uma entity rotacionada, use `Transform.localToWorldDirection()` para convertê-la primeiro — veja [Converter uma direção local para world space](#convert-a-local-direction-to-world-space).

Tal como `applyImpulseToPlayer()`, você também pode passar uma `direção` e `magnitude` separadamente — veja [Aplicar um impulso](#apply-an-impulse):

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

Se você chamar `applyForceToPlayer()` novamente com a mesma source entity, ele substitui a força anterior dessa origem. Se múltiplas origens de força forem acumuladas, seus vetores são somados a cada tick.

### Remover uma força contínua

Para parar de aplicar uma força, chame `Physics.removeForceFromPlayer()` com uma referência à source entity que foi usada para criar a força. Se a entity não estiver aplicando uma força no momento, essa chamada será ignorada com segurança.

* `source`: A entity usada quando a força foi aplicada.

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

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

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

* `source`: Uma entity que identifica essa origem da força.
* `duração`: Por 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()

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

O `direção` + `magnitude` a sobrecarga também está disponível — veja [Aplicar 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))  // empurrar 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. Isso é 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. Diferente de `applyKnockbackToPlayer()`, essa força é recalculada a cada tick conforme o jogador se move. A magnitude enfraquece com a distância com base no raio e no falloff — veja [Aplicar um impulso de knockback](#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 um poço gravitacional.

{% hint style="warning" %}
**📔 Nota**: A origem da repulsão é o `fromPosition` vetor que você passa — **não** a posição da `source` entity. A `source` entity é usada apenas como identificador, para que você possa atualizar ou remover a força mais tarde. Sua posição, rotação e escala são completamente ignoradas.
{% endhint %}

* `source`: Uma entity usada como identificador para essa força — sua posição não é usada.
* `fromPosition`: O ponto no espaço global do qual o jogador é afastado.
* `magnitude`: Força base. Valores negativos atraem em vez de repelir.
* `raio`: Distância máxima de efeito (padrão: `Infinity`).
* `falloff`: Como a magnitude diminui com a distância (padrã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) })

// Passar explicitamente a posição da entity 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
)

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

## Forças enquanto plana

Enquanto o jogador está planando, as forças contínuas se comportam de maneira diferente:

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

Impulsos de uso único — de `applyImpulseToPlayer()` ou `applyKnockbackToPlayer()` — não são afetados pelo planador. Eles se comportam da mesma forma, esteja o planador aberto ou fechado.

Você pode combinar esses comportamentos para criar mecânicas como correntes térmicas ascendentes que levam jogadores planando 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 frente do planador, use o `AvatarLocomotionSettings` componente, veja [Configurações de locomoção](/creator/content-creator-pt/scenes-sdk7/interatividade/avatars/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 de coordenadas local de uma entity para o espaço global, considerando toda a hierarquia de pais. Isso é útil ao aplicar forças relativas a uma entity rotacionada — por exemplo, empurrar o jogador para longe de uma face específica de um obstáculo giratório.

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

Retorna o vetor de direção nas coordenadas globais.

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

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

// Empurrar o jogador na direção para a qual o eixo local +Z da entity aponta no 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 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-pt/scenes-sdk7/interatividade/player-physics.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.
