> 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 jogador

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

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

* **Impulse**: 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 para trás.
* **Continuous force**: 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 por meio 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 outros jogadores, mas as forças em si não são sincronizadas para os outros jogadores no multiplayer. A física de cada jogador é executada localmente na sua própria instância.
{% endhint %}

## Aplicar um impulso

Use `Physics.applyImpulseToPlayer()` para dar ao jogador um empurrão de uso único em uma direção específica.

* `vector`: Direção e força combinadas — o comprimento do vector 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))
```

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

* `direction`: Direção para empurrar — normalizada automaticamente antes da escala.
* `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 você chamar `applyImpulseToPlayer()` várias vezes dentro do mesmo frame, os impulses são acumulados — eles 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 em uma área. Use uma trigger area para detectar quando o jogador entra:

```ts
import { 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 empurrar o jogador para longe 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 a partir 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)

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

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

* `fromPosition`: Origem do knockback no espaço do mundo (centro da explosão, posição do inimigo etc.).
* `magnitude`: Força base do impulso.
* `radius`: 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,                          // radius: sem efeito além de 10 metros
	KnockbackFalloff.LINEAR      // a magnitude desaparece até 0 na borda do radius
)
```

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

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

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

Os mesmos `KnockbackFalloff` values 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 impulse, essa força é aplicada a cada tick enquanto permanecer ativa.

* `source`: Uma entity que identifica essa origem da força — use-a para atualizar ou remover a força depois.
* `vector`: Direção e força combinadas — o comprimento do vector codifica a magnitude da força.

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

```ts
import { 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 vector 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 [Convert a local direction to world space](#convert-a-local-direction-to-world-space).

Assim como em `applyImpulseToPlayer()`, você também pode passar uma `direction` 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, ela substitui a força anterior dessa origem. Se várias fontes de força forem acumuladas, seus vectors 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 é ignorada com segurança.

* `source`: A entity 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 por uma quantidade específica de tempo. A duração é em segundos. A força é removida automaticamente quando o tempo se esgota. Chamar isso novamente com a mesma source entity reinicia o temporizador.

* `source`: Uma entity que identifica essa source da força.
* `duration`: Por quanto tempo a força dura, em segundos.
* `vector`: Direção e força combinadas — o comprimento do vector codifica a magnitude da força.

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

const gustEntity = engine.addEntity()

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

O `direction` + `magnitude` overload 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 estiver dentro dele e para quando ele sai:

```ts
import { 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. 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. Ao contrário de `applyKnockbackToPlayer()`, essa força é recalculada a cada tick conforme o jogador se move. A magnitude enfraquece com a distância com base no radius 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 vortex ou um poço gravitacional.

{% hint style="warning" %}
**📔 Nota**: A origem da repulsão é o `fromPosition` vector 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 depois. 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 do mundo do qual o jogador é afastado.
* `magnitude`: Força base da força. Valores negativos atraem em vez de repelir.
* `radius`: Distância máxima de efeito (padrão: `Infinity`).
* `falloff`: Como a magnitude diminui com a distância (padrão: `CONSTANT`).

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

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

// Passe 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,                                         // radius de efeito em metros
)

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

## Convert a local direction to world space

Use `Transform.localToWorldDirection()` para transformar um vector de direção do espaço de coordenadas local de uma entity para o world space, considerando toda a hierarquia de parents. 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`: Vector de direção nas coordenadas locais da entity.

Retorna o vector de direção em coordenadas do mundo.

Isso aplica **apenas rotação** — não leva em conta translação ou escala — tornando-o diretamente adequado para vectors 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'

// Empurra o jogador na direção em que o eixo +Z local 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.
