> 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-ko/sdk7/interactivity/player-physics.md).

# 플레이어 물리

플레이어 아바타에 힘과 충격량을 적용합니다

장면 코드에서 플레이어의 아바타에 물리적 힘을 적용할 수 있습니다. 이를 통해 점프 패드, 바람 구역, 넉백 효과, 폭발 등과 같은 게임플레이 메커니즘을 만들 수 있습니다.

적용할 수 있는 힘에는 두 가지가 있습니다:

* **임펄스**: 한 번만 작동하는 즉시적인 밀기입니다. 플레이어를 공중으로 띄우거나 뒤로 밀치는 것처럼 갑작스럽고 분리된 효과에 사용하세요.
* **연속 힘**: 활성 상태인 동안 매 틱마다 적용되는 지속적인 밀기입니다. 바람 구역, 물살, 중력장 같은 지속 효과에 사용하세요.

둘 다 다음을 통해 적용됩니다: `Physics` 헬퍼를 통해 적용하며, 다음에서 가져옵니다: `@dcl/sdk/ecs`.

{% hint style="warning" %}
**📔 참고**이 힘들은 로컬 플레이어의 아바타에만 영향을 줍니다. 다른 플레이어는 다른 플레이어의 위치 변화는 보지만, 힘 자체는 멀티플레이에서 다른 플레이어와 동기화되지 않습니다. 각 플레이어의 물리는 자신의 인스턴스에서 로컬로 실행됩니다.
{% endhint %}

## 임펄스 적용하기

다음을 사용하세요 `Physics.applyImpulseToPlayer()` 를 사용해 플레이어를 주어진 방향으로 한 번 밀어냅니다.

* `벡터`: 방향과 강도가 결합된 값으로, 벡터의 길이가 임펄스 크기를 나타냅니다.

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

// 플레이어를 곧바로 위로 띄우기
Physics.applyImpulseToPlayer(Vector3.create(0, 50, 0))
```

방향과 크기를 별도로 전달할 수도 있습니다. 이 경우 방향 벡터는 자동으로 정규화됩니다:

* `방향`: 밀어낼 방향 — 스케일링하기 전에 자동으로 정규화됩니다.
* `크기`: 임펄스 강도.

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

// 플레이어를 크기 50으로 위로 띄우기
Physics.applyImpulseToPlayer(Vector3.create(0, 1, 0), 50)
```

다음 함수를 호출하면 `applyImpulseToPlayer()` 같은 프레임 안에서 여러 번 호출해도 임펄스는 누적됩니다. 즉, 서로 더해져 하나의 결합된 임펄스로 적용됩니다.

### 플레이어 진입 시 임펄스 트리거하기

일반적인 패턴은 플레이어가 영역에 들어왔을 때 임펄스를 트리거하는 것입니다. 플레이어가 들어오는 것을 감지하려면 트리거 영역을 사용하세요:

```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))
})
```

## 넉백 임펄스 적용하기

다음을 사용하세요 `Physics.applyKnockbackToPlayer()` 플레이어를 한 번의 임펄스로 특정 지점에서 멀어지게 밀어냅니다. 이는 폭발, 충격 효과, 기타 한 번만 작동하는 방향성 폭발에 이상적입니다. 방향은 원점에서 플레이어의 현재 위치까지 자동으로 계산됩니다.

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

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

// 플레이어를 폭발 중심에서 멀리 밀어내기
Physics.applyKnockbackToPlayer(explosionPosition, 40)
```

다음을 사용하여 효과 범위를 제한할 수 있습니다: `반경`, 그리고 다음을 사용하여 거리와 함께 크기가 어떻게 감소하는지 제어할 수 있습니다: `KnockbackFalloff` 옵션:

* `시작 위치`: 월드 공간상의 넉백 원점(폭발 중심, 적의 위치 등).
* `크기`: 기본 임펄스 강도.
* `반경`: 효과의 최대 거리(기본값: `Infinity`).
* `감쇠`: 크기가 거리에 따라 어떻게 감소하는지(기본값: `CONSTANT`).

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

Physics.applyKnockbackToPlayer(
	Vector3.create(8, 1, 8),
	40,                          // 크기
	10,                          // 효과 반경: 10미터를 넘으면 효과 없음
	KnockbackFalloff.LINEAR      // 크기가 반경 경계에서 0까지 감소
)
```

이 `KnockbackFalloff` 이 열거형은 힘이 거리에 따라 어떻게 감소하는지 제어합니다:

* `KnockbackFalloff.CONSTANT` — 반경 내의 어느 거리에서나 같은 크기(기본값)
* `KnockbackFalloff.LINEAR` — 반경 경계까지 부드럽게 선형 감소
* `KnockbackFalloff.INVERSE_SQUARE` — 급격하고 물리적으로 사실적인 감쇠

플레이어가 정확히 원점 위치에 있으면 플레이어는 곧바로 위로 밀려납니다. 음수 크기는 플레이어를 밀어내는 대신 해당 지점 쪽으로 끌어당깁니다.

마찬가지로 `KnockbackFalloff` 값을 다음에도 사용할 수 있습니다: `applyRepulsionForceToPlayer()`.

## 연속 힘 적용하기

다음을 사용하세요 `Physics.applyForceToPlayer()` 플레이어에게 지속적인 힘을 적용합니다. 임펄스와 달리 이 힘은 활성 상태인 동안 매 틱마다 적용됩니다.

* `원천`: 이 힘의 원천을 식별하는 엔티티 — 나중에 힘을 업데이트하거나 제거할 때 사용합니다.
* `벡터`: 벡터의 길이가 힘의 크기를 나타내는, 방향과 강도가 결합된 값입니다.

소스 엔티티의 위치는 중요하지 않습니다. 식별자로만 사용됩니다.

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

const windZoneEntity = engine.addEntity()

// 플레이어를 오른쪽으로 지속적으로 밀기
Physics.applyForceToPlayer(windZoneEntity, Vector3.create(10, 0, 0))
```

힘 벡터는 항상 **월드 공간**입니다. 회전한 엔티티를 기준으로 한 방향이 필요하다면 다음을 사용하세요: `Transform.localToWorldDirection()` 먼저 변환하세요 — 다음을 참조: [로컬 방향을 월드 공간으로 변환하기](#convert-a-local-direction-to-world-space).

다음과 마찬가지로 `applyImpulseToPlayer()`, 다음도 별도로 전달할 수 있습니다 `방향` 과 `크기` — 다음을 참조: [임펄스 적용하기](#apply-an-impulse):

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

다음 함수를 호출하면 `applyForceToPlayer()` 다시 같은 소스 엔티티에 대해 호출하면 해당 소스의 이전 힘을 대체합니다. 여러 힘의 원천이 누적되면 각 틱마다 그 벡터가 합산됩니다.

### 연속 힘 제거하기

힘 적용을 중지하려면 `Physics.removeForceFromPlayer()` 힘을 생성할 때 사용한 소스 엔티티에 대한 참조를 함께 호출하세요. 엔티티가 현재 힘을 적용 중이 아니어도 이 호출은 안전하게 무시됩니다.

* `원천`: 힘을 적용할 때 사용한 엔티티.

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

### 제한된 시간 동안 힘 적용하기

다음을 사용하세요 `Physics.applyForceToPlayerForDuration()` 특정 시간 동안 힘을 적용합니다. 지속 시간은 초 단위입니다. 시간이 지나면 힘은 자동으로 제거됩니다. 같은 소스 엔티티로 다시 호출하면 타이머가 재설정됩니다.

* `원천`: 이 힘의 원천을 식별하는 엔티티.
* `지속 시간`: 힘이 지속되는 시간(초).
* `벡터`: 벡터의 길이가 힘의 크기를 나타내는, 방향과 강도가 결합된 값입니다.

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

const gustEntity = engine.addEntity()

// 1.5초 동안 강한 위쪽 힘 적용
Physics.applyForceToPlayerForDuration(gustEntity, 1.5, Vector3.create(0, 50, 0))
```

이 `방향` + `크기` 오버로드도 사용할 수 있습니다 — 다음을 참조: [임펄스 적용하기](#apply-an-impulse):

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

### 바람 구역 예제

이 예제는 플레이어가 안에 있는 동안 밀어주고, 나가면 멈추는 풍동을 만듭니다:

```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))  // X축을 따라 옆으로 밀기
})

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

## 반발력 적용하기

다음을 사용하세요 `Physics.applyRepulsionForceToPlayer()` 공간의 고정된 지점으로부터 플레이어를 지속적으로 밀어내는 데 사용합니다. 자기장 반발장, 힘의 장벽, 혹은 플레이어를 일정 거리 밖에 유지하는 떠 있는 물체 같은 효과에 적합합니다.  `applyKnockbackToPlayer()`과 달리, 이 힘은 플레이어가 움직일 때마다 매 틱 재계산됩니다. 크기는 반경과 감쇠에 따라 거리와 함께 약해집니다 — 다음에 대한 [넉백 임펄스 적용하기](#apply-a-knockback-impulse) 옵션은 `KnockbackFalloff` 다음을 참조하세요. 음수 크기는 효과를 반대로 바꾸어, 소용돌이나 중력 우물처럼 플레이어를 지점 쪽으로 지속적으로 끌어당깁니다.

{% hint style="warning" %}
**📔 참고**: 반발의 원점은 `시작 위치` 전달한 벡터입니다 — **아니라** 해당 `원천` 엔티티의 위치입니다.  `원천` 엔티티는 나중에 힘을 업데이트하거나 제거할 수 있도록 식별자로만 사용됩니다. 위치, 회전, 크기는 완전히 무시됩니다.
{% endhint %}

* `원천`: 이 힘의 식별자로 사용하는 엔티티 — 위치는 사용되지 않습니다.
* `시작 위치`: 플레이어가 밀려나는 월드 공간상의 지점.
* `크기`: 기본 힘의 강도. 음수 값은 반발 대신 끌어당깁니다.
* `반경`: 효과의 최대 거리(기본값: `Infinity`).
* `감쇠`: 크기가 거리에 따라 어떻게 감소하는지(기본값: `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) })

// 엔티티의 위치를 반발 원점으로 명시적으로 전달
Physics.applyRepulsionForceToPlayer(
	repulsionSource,
	Transform.get(repulsionSource).position,  // 반발 원점 — 자동으로 읽지 않고 명시적으로 전달
	50,                                         // 크기
	10,                                         // 효과 반경(미터)
)

// 0.5초 후 힘 제거
timers.setTimeout(() => {
    Physics.removeForceFromPlayer(repulsionSource)
}, 500)
```

## 글라이딩 중의 힘

플레이어가 글라이딩 중일 때, 연속 힘은 다르게 작동합니다:

* 연속 힘은 — `applyForceToPlayer()`, `applyForceToPlayerForDuration()`또는 `applyRepulsionForceToPlayer()` —은 **1.5배 더 강해집니다**, 펼친 글라이더가 공기 흐름을 받아들이기 때문입니다. 바람 구역과 해류는 글라이딩 중인 플레이어에게 더 민감하게 느껴집니다.
* 연속 힘의 위쪽 성분은 **들어 올릴 수 있습니다** 글라이딩 중인 플레이어를. 글라이더의 낙하 속도 제한은 플레이어가 내려가는 속도만 제한할 뿐, 위쪽 움직임은 상쇄하지 않으므로, 기울어진 또는 수직 바람 흐름은 힘의 전체 방향으로 플레이어를 밀어줍니다.

한 번만 작동하는 임펄스는 — `applyImpulseToPlayer()` 또는 `applyKnockbackToPlayer()` — 글라이딩의 영향을 받지 않습니다. 글라이더가 열려 있든 닫혀 있든 동일하게 작동합니다.

이러한 동작을 조합하여 글라이딩 플레이어를 위로 끌어올리는 상승 기류나, 글라이더를 펼쳤을 때 더 쉽게 통과할 수 있는 바람 통로 같은 메커니즘을 만들 수 있습니다. 글라이더의 낙하 속도나 전진 속도를 조정하려면 `AvatarLocomotionSettings` 구성 요소를 사용하세요. 다음을 참조: [이동 설정](/creator/content-creator-ko/sdk7/interactivity/avatars/locomotion.md#locomotion-settings).

## 로컬 방향을 월드 공간으로 변환하기

다음을 사용하세요 `Transform.localToWorldDirection()` 엔티티의 로컬 좌표 공간에서 방향 벡터를 전체 부모 계층을 고려하여 월드 공간으로 변환합니다. 회전한 엔티티를 기준으로 힘을 적용할 때 유용합니다. 예를 들어 회전하는 장애물의 특정 면에서 플레이어를 밀어내는 경우입니다.

* `엔티티`: 방향을 정의하는 로컬 공간의 소스 엔티티.
* `로컬 방향`: 엔티티의 로컬 좌표계에 있는 방향 벡터.

월드 좌표의 방향 벡터를 반환합니다.

이는 **회전만** — 이동이나 스케일은 고려하지 않습니다 — 따라서 힘 및 임펄스 함수에 전달되는 방향 벡터에 직접 사용하기에 적합합니다.

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

// 엔티티의 로컬 +Z 축이 가리키는 방향을 월드 공간으로 밀어내기
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-ko/sdk7/interactivity/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.
