> 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/3d/entity-positioning.md).

# 엔터티 배치

씬에서 엔터티의 위치, 회전 및 크기를 설정하는 방법

다음을 설정하여 *위치*, *회전* 및 *크기* 의 어떤 엔티티든 다음을 사용하여 `Transform` 컴포넌트. 이는 3D 공간의 어떤 엔티티에도 사용할 수 있으며, 엔티티가 렌더링되는 위치에 영향을 줍니다. 여기에는 기본 도형(큐브, 구, 평면 등), 3D 텍스트 도형, NFT 도형, 3D 모델(`GltfContainer`).

## Creator Hub의 Scene Editor를 사용하세요

Scene Editor를 통해 씬에 항목을 추가하면, 암묵적으로 다음이 포함됩니다: **Transform** 컴포넌트. 그런 다음 엔티티의 위치, 회전 또는 스케일을 변경하여 엔티티의 Transform 컴포넌트 값이 암묵적으로 바뀝니다. 더 높은 정밀도가 필요하면 Scene Editor의 UI에서 수치를 직접 입력할 수도 있습니다.

## 코드 핵심

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-417a02dcf0fd40f5032551a0c6996becac7e7166%2Fecs-simple-components-new.png?alt=media)

```ts
// 새 엔티티 생성
const ball = engine.addEntity()

// 이 엔티티에 모양을 지정하여 보이게 만들기
MeshRenderer.setSphere(ball)

// 이 엔티티에 Transform 컴포넌트 추가
Transform.create(ball, {
	position: Vector3.create(5, 1, 5),
	scale: Vector3.create(1, 1, 1),
	rotation: Quaternion.Identity(),
})
```

씬의 엔티티를 일정 시간에 걸쳐 이동, 회전 또는 크기 조정하려면 이 컴포넌트의 값을 프레임마다 조금씩 변경하세요. 자세한 내용과 모범 사례는 다음을 참조하세요. [엔티티 이동](/creator/content-creator-ko/sdk7/3d/move-entities.md) 자세한 내용과 모범 사례를 참조하세요.

{% hint style="warning" %}
**📔 참고**: `Vector3` 및 `Quaternion` 는 다음을 통해 가져와야 합니다

> `import { Vector3, Quaternion } from "@dcl/sdk/math"`

참고 [가져오기](/creator/content-creator-ko/sdk7/getting-started/coding-scenes.md#imports) 를 사용하면 이를 쉽게 처리할 수 있습니다.
{% endhint %}

## 위치

`위치` 는 *3D 벡터*, 엔티티 중심의 위치를 세 축 모두에 설정합니다, *x*, *y*, 그리고 *부터*. 자세한 내용은 [기하 도형 유형](/creator/content-creator-ko/sdk7/3d/special-types.md) 자세한 내용은 다음을 참조하세요.

```ts
// 새 엔티티 생성
const ball = engine.addEntity()

// 미리 정의된 위치로 Transform 생성
Transform.create(ball, {
	  position: Vector3.create(5, 1, 5)
})

// Transform의 수정 가능한 버전 가져오기
const mutableTransform = Transform.getMutable(ball)

// 객체로 위치 설정
mutableTransform.position = { x: 5, y: 1, z: 5 }

// 객체로 위치 설정(대체 구문)
mutableTransform.position = Vector3.create(2, 1, 4)

// 각 축을 개별적으로 설정
mutableTransform.position.x = 3
mutableTransform.position.y = 1
mutableTransform.position.z = 3
```

위치를 설정할 때는 다음 사항을 염두에 두세요:

* 위치 벡터의 숫자는 *미터* (엔티티가 스케일된 엔티티의 자식인 경우는 제외).
* 단일 패킷으로 구성된 씬의 크기는 16m x 16m입니다. 씬의 중심(지면 기준)은 다음 위치에 있습니다: `x:8, y:0, z:8`. 씬이 여러 패킷으로 구성된 경우, 중심은 배치에 따라 달라집니다.
* `x:0, y:0, z:0` 는 다음을 가리킵니다: *남서쪽* 씬의 기본 패킷의 모서리, 지면 기준.

  > 팁: 씬 미리보기를 볼 때, 씬의 (0,0,0) 지점에 나침반이 나타나며 각 축의 레이블이 기준으로 표시됩니다.

  > 참고: 씬의 기본 패킷은 다음을 편집하여 변경할 수 있습니다: `base` 의 속성 *scene.json*.
* 방향을 더 쉽게 파악하려면 손을 사용하세요: *left* 손:
  * 검지손가락(앞을 가리키는 손가락)은 *부터* 축
  * 중지손가락(옆을 가리키는 손가락)은 *x* 축
  * 엄지손가락(위로 가리키는 손가락)은 *y* 축입니다.
* 엔티티가 다른 엔티티의 자식인 경우, `x:0, y:0, z:0` 는 씬의 어디에 있든 부모 엔티티의 중심을 가리킵니다.
* 씬의 모든 엔티티는 항상 자신이 차지하는 패킷의 경계 안에 위치해야 합니다. 엔티티가 이 경계를 벗어나면 오류가 발생합니다.

  > 팁: 미리보기 모드에서 씬을 볼 때, 경계를 벗어난 엔티티는 다음 색으로 강조 표시됩니다: *red*.
* 씬의 높이에도 제한이 있습니다. 씬을 구성하는 패킷이 많을수록 더 높게 지을 수 있습니다. 다음을 참조하세요: [씬 제한 사항](/creator/content-creator-ko/sdk7/optimizing/scene-limitations.md) 자세한 내용은 다음을 참조하세요.

## 회전

`회전` 는 다음 형식으로 저장됩니다: [*쿼터니언*](https://en.wikipedia.org/wiki/Quaternion), 네 개의 숫자로 이루어진 체계인 *x*, *y*, *부터* 및 *w*. 이 숫자들은 각각 -1에서 1 사이의 값을 가집니다. 다음을 참조하세요: [기하 도형 유형](/creator/content-creator-ko/sdk7/3d/special-types.md) 자세한 내용은 다음을 참조하세요.

```ts
// 새 엔티티 생성
const cube = engine.addEntity()

// 미리 정의된 0 회전으로 Transform 생성
Transform.create(cube, {
	  rotation: Quaternion.Identity()
})

// Transform의 수정 가능한 버전 가져오기
const mutableTransform = Transform.getMutable(cube)

// 오일러 각으로 객체를 사용해 회전 설정
mutableTransform.rotation = Quaternion.fromEulerDegrees(0, 90, 0)

// 객체로 회전 설정
mutableTransform.rotation = { x: 0.1, y: 0.5, z: 0.5, w: 0 }

// 각 축을 개별적으로 설정
mutableTransform.rotation.x = 0
mutableTransform.rotation.y = 1
mutableTransform.rotation.z = 0.3
mutableTransform.rotation.w = 0
```

회전 필드는 다음으로도 설정할 수 있습니다: [*오일러* 각](https://en.wikipedia.org/wiki/Euler_angles), 더 일반적인 *x*, *y* 및 *부터* 0에서 360까지의 숫자를 사용하는 표기법으로, 대부분의 사람들이 익숙한 방식입니다. 오일러 각을 사용하려면 다음 표기 중 하나를 사용하세요:

```ts
// 오일러 각으로 미리 정의된 회전으로 Transform 생성
Transform.create(cube, {
	  rotation: Quaternion.fromEulerDegrees(0, 90, 0)
})

// Transform의 수정 가능한 버전 가져오기
const mutableTransform = Transform.getMutable(cube)

// 오일러 각으로 객체를 사용해 회전 설정
mutableTransform.rotation = Quaternion.fromEulerDegrees(0, 90, 0)
```

다음을 사용할 때 *3D 벡터* 오일러 각을 나타내기 위해 *x*, *y* 및 *부터* 해당 축의 회전을 나타냅니다. 각도는 도 단위로 측정됩니다. 한 바퀴는 360도입니다.

엔티티의 회전을 가져오면 기본적으로 쿼터니언이 반환됩니다. 회전을 오일러 각으로 표현하려면 다음을 사용하세요: `Quaternion.toEulerAngles()`:

```ts
// 읽기 전용 Transform 버전 가져오기
const transform = Transform.get(cube)

// 오일러 각으로 표현된 회전 가져오기
const eulerAngle = Quaternion.toEulerAngles(transform.rotation)
```

## 엔티티의 전역 위치와 회전 가져오기

그 `getWorldPosition` 및 `getWorldRotation` 함수는 엔티티의 전역 위치와 회전을 반환합니다. 즉, 부모 계층 구조는 무시하고 플레이어가 보게 될 엔티티의 인식된 위치나 회전을 반환합니다.

* `getWorldPosition(engine, entity: Entity): Vector3Type`: 이 함수는 엔티티의 World 위치를 반환합니다. 엔티티 자체에 부모 엔티티가 있는 경우 그 모든 위치를 고려하며, 다음을 반환합니다: `{x: 0, y: 0, z: 0}` 엔티티에 Transform이 없는 경우.

```ts
const worldPos = getWorldPosition(engine, childEntity)
console.log(`월드 위치: ${worldPos.x}, ${worldPos.y}, ${worldPos.z}`)
```

* `getWorldRotation(engine, entity: Entity): QuaternionType`: 이 함수는 엔티티의 World 회전을 반환합니다. 엔티티 자체에 부모 엔티티가 있는 경우 그 모든 회전을 고려합니다. 반환 값은 다음 `Quaternion` 형식이며, 항등 쿼터니언을 반환합니다 `{x: 0, y: 0, z: 0, w: 1}` 엔티티에 Transform이 없는 경우.

```ts
const worldRot = getWorldRotation(engine, childEntity)
console.log(`월드 회전: ${worldRot.x}, ${worldRot.y}, ${worldRot.z}, ${worldRot.w}`)
```

{% hint style="info" %}
**참고:** 전역 위치와 전역 회전은 Genesis City가 아니라 씬 내부의 좌표를 기준으로 합니다.
{% endhint %}

## 플레이어를 향하게 하기

다음을 추가하세요 *빌보드* 컴포넌트를 엔티티에 추가하여 항상 플레이어를 향하도록 회전하게 합니다.

빌보드는 90년대 3D 게임에서 흔히 사용되던 기법으로, 대부분의 엔티티가 항상 플레이어를 향하는 2D 평면이었습니다. 같은 아이디어를 3D 모델 회전에도 사용할 수 있습니다.

```ts
// 새 엔티티 생성
const cube = engine.addEntity()

// 엔티티에 보이는 모양 지정
MeshRenderer.setBox(cube)

// 미리 정의된 위치로 Transform 생성
Transform.create(cube, {
	  position: Vector3.create(5, 1, 5)
})

// 엔티티에 Billboard 컴포넌트 추가
Billboard.create(cube, {})
```

다음 매개변수로 빌보드의 동작을 설정할 수 있습니다:

* `billboardMode`: 다음 값 중 하나를 사용합니다: `BillboardMode` 를 사용하여 어떤 회전 축이 자동으로 플레이어를 향해 회전할지 설정합니다:
  * `BillboardMode.BM_ALL`: 엔티티는 모든 회전 축에서 플레이어를 향하도록 회전합니다. 플레이어가 엔티티보다 훨씬 높은 위치에 있으면 엔티티는 위를 향하게 됩니다.
  * `BillboardMode.BM_NONE`: 엔티티는 전혀 회전하지 않습니다.
  * `BillboardMode.BM_X`: 엔티티는 오직 자체의 *x* 회전 축에서만 회전합니다.
  * `BillboardMode.BM_Y`: 엔티티는 오직 자체의 *y* 회전 축입니다. 위아래가 아니라 좌우로만 회전합니다. 플레이어가 엔티티 위나 아래에 있어도 지면에 수직인 상태를 유지합니다.
  * `BillboardMode.BM_Z`: 엔티티는 오직 자체의 *부터* 회전 축에서만 회전합니다.
* `targetEntity`: (선택 사항) 플레이어 카메라 대신 빌보드가 바라보도록 회전할 엔티티입니다. 참조된 엔티티가 존재하지 않으면(예: 아직 생성되지 않았거나 제거된 경우) 빌보드는 회전을 멈추고 엔티티가 다시 존재할 때까지 마지막 방향을 유지합니다. 이를 다음으로 설정하면 `engine.CameraEntity` 설정하지 않은 것과 같습니다.

```ts
// 평면 빌보드
const perpendicularPlane = engine.addEntity()

Transform.create(perpendicularPlane, {
	position: Vector3.create(8, 1, 8),
})

MeshRenderer.setPlane(perpendicularPlane)

Billboard.create(perpendicularPlane, {
	billboardMode: BillboardMode.BM_Y,
})

// 텍스트 라벨
const textLabel = engine.addEntity()

Transform.create(textLabel, {
	position: Vector3.create(6, 1, 6),
})

TextShape.create(textLabel, {
	text: '이 텍스트는 항상 읽을 수 있습니다',
})

Billboard.create(textLabel)

// 플레이어 대신 다른 엔티티를 바라보는 표지판
const sphere = engine.addEntity()

Transform.create(sphere, {
	position: Vector3.create(4, 2, 4),
})

MeshRenderer.setSphere(sphere)

const sign = engine.addEntity()

Transform.create(sign, {
	position: Vector3.create(8, 1, 8),
})

TextShape.create(sign, {
	text: '구를 바라보는 중',
})

Billboard.create(sign, {
	targetEntity: sphere,
})
```

{% hint style="info" %}
**💡 팁**: 빌보드는 다음에 추가하면 매우 유용합니다: *text* 엔티티는 항상 읽을 수 있게 되기 때문입니다.
{% endhint %}

그 `회전` 엔티티의 `Transform` 컴포넌트 값은 빌보드가 플레이어를 따라다녀도 변하지 않습니다.

엔티티에 다음 두 가지가 모두 있으면: `빌보드` 컴포넌트와 `Transform` 사용해 컴포넌트를 `회전` 값이 있으면, 플레이어는 엔티티가 빌보드처럼 회전하는 것을 보게 됩니다. 빌보드가 모든 축에 영향을 주지 않는 경우, 나머지 축은 다음에 따라 회전합니다: `Transform` 컴포넌트를 부여해야 합니다.

{% hint style="warning" %}
**📔 참고**: 동시에 여러 플레이어가 있더라도, 각자 자신을 향하고 있는 빌보드 모드의 엔티티를 보게 됩니다. 빌보드 회전은 각 플레이어에 대해 로컬로 계산되며, 다른 플레이어가 보는 것에는 영향을 주지 않습니다. 다음이 있는 빌보드에는 적용되지 않습니다: `targetEntity`: 대상의 위치가 씬의 일부이므로, 모든 플레이어는 해당 빌보드를 같은 방향으로 보게 됩니다.
{% endhint %}

## 좌표 집합을 바라보기

엔티티 A가 엔티티 B를 바라보게 하려면:

```
1) 엔티티 A의 위치를 엔티티 B의 위치에서 빼 두 엔티티 사이의 거리를 나타내는 벡터를 구합니다.
2) 그 벡터를 정규화하여 길이가 1이 되도록 하고, 방향은 유지합니다.
3) `Quaternion.lookRotation`을 사용하여 그 방향으로 회전하는 쿼터니언 회전을 구합니다.
4) 그 쿼터니언을 엔티티 A의 회전으로 설정합니다.
```

```ts
export function turn(entity: Entity, target: Vector3.ReadonlyVector3) {
	const transform = Transform.getMutable(entity)
	const difference = Vector3.subtract(target, transform.position)
	const normalizedDifference = Vector3.normalize(difference)
	transform.rotation = Quaternion.lookRotation(normalizedDifference)
}
```

## 스케일

`크기` 도 다음과 같이 *3D 벡터*, 다음 형식으로 저장됩니다: `Vector3` 객체이며, 다음의 스케일 계수를 포함합니다: *x*, *y* 및 *부터* 축. 엔티티의 모양은 기본 도형이든 3D 모델이든 이에 맞게 조정됩니다.

기본 스케일은 1입니다. 따라서 1보다 큰 값을 주면 엔티티가 늘어나고, 1보다 작은 값을 주면 줄어듭니다.

```ts
// 새 엔티티 생성
const ball = engine.addEntity()

// 미리 정의된 위치로 Transform 생성
Transform.create(ball, {
	  scale: Vector3.create(5, 5, 5)
})

// Transform의 수정 가능한 버전 가져오기
const mutableTransform = Transform.getMutable(ball)

// Vector3로 스케일 설정

mutableTransform.scale = Vector3.create(2, 2, 2)

// 객체로 위치 설정
mutableTransform.scale = { x: 5, y: 1, z: 5 }

// 각 축을 개별적으로 설정
mutableTransform.scale.x = 3
mutableTransform.scale.y = 3
mutableTransform.scale.z = 2
```

## 부모의 변형 상속

엔티티가 다른 엔티티 안에 중첩되면 자식 엔티티는 부모의 컴포넌트를 상속합니다. 즉, 부모 엔티티가 위치 이동, 크기 조정, 회전되면 자식도 영향을 받습니다. 자식 엔티티의 위치, 회전, 스케일 값은 부모의 값을 덮어쓰지 않고, 대신 이 값들이 누적됩니다.

엔티티를 다른 엔티티의 부모로 지정하려면 다음을 설정합니다: `parent` 자식 엔티티의 `Transform` 컴포넌트를 부여해야 합니다.

부모 엔티티가 스케일되면 자식의 모든 위치 값도 함께 스케일됩니다.

```ts
// 엔티티 생성
const parentEntity = engine.addEntity()
const childEntity = engine.addEntity()

// 부모의 Transform 생성
Transform.create(parentEntity, {
	position: Vector3.create(3, 1, 1),
	scale: Vector3.create(0.5, 0.5, 0.5),
})

// 자식의 Transform을 생성하고 자식으로 지정
Transform.create(childEntity, {
	position: Vector3.create(0, 1, 0),
	parent: parentEntity,
})
```

이 예제에서는 부모가 해당 스케일을 가지므로 자식 엔티티의 스케일은 0.5로 줄어듭니다. 자식 엔티티의 위치도 부모를 기준으로 상대적입니다. 부모의 위치에 자식의 위치를 더해야 합니다. 이 경우 부모가 절반 크기로 스케일되었기 때문에 자식의 변형도 비례하여 줄어듭니다. 절대적으로는 자식이 다음 위치에 놓입니다: `{ x: 3, y: 1.5, z: 1 }`. 부모가 다음을 가지고 있었다면 `회전`, 이는 자식이 이동하는 축을 바꾸므로 자식의 최종 위치에도 영향을 줍니다.

자식 엔티티에 다음이 없으면 `위치` Transform에 있는 경우 기본값은 `0,0,0`, 부모와 같은 위치에 있게 됩니다.

모양 컴포넌트가 없는 보이지 않는 엔티티를 부모로 사용해 다른 엔티티들을 묶을 수 있습니다. 이 엔티티는 렌더링된 씬에 보이지 않지만, 자식들을 그룹화하고 모두에 변형을 적용하는 데 사용할 수 있습니다.

{% hint style="warning" %}
**📔 참고**: 계층 구조에서 엔티티가 결국 자기 자신의 조상이 되는 루프를 만들지 마세요. SDK는 이러한 루프를 감지하고 관련 엔티티 이름과 함께 경고를 기록합니다. 부모-자식 관계를 수정하기 전까지 영향받은 엔티티는 올바르게 배치되지 않습니다.
{% endhint %}

## 엔티티를 아바타에 부착하기

엔티티를 플레이어에 연결하는 방법은 세 가지입니다:

* 다음의 자식으로 만드세요: **Avatar Entity**
* 다음의 자식으로 만드세요: **Camera Entity**
* 사용하세요 **AvatarAttach 컴포넌트**

엔티티를 아바타에 연결하는 가장 간단한 방법은 부모를 다음으로 설정하는 것입니다: [예약된 엔티티](/creator/content-creator-ko/sdk7/architecture/entities-components.md#reserved-entities) `engine.PlayerEntity`. 그러면 엔티티는 플레이어의 위치와 함께 이동합니다.

```ts
let childEntity = engine.addEntity()

MeshRenderer.setCylinder(childEntity)

Transform.create(childEntity, {
	scale: Vector3.create(0.2, 0.2, 0.2),
	position: Vector3.create(0, 0.4, 0),
	parent: engine.PlayerEntity,
})
```

엔티티를 다음으로 설정할 수도 있습니다: [예약된 엔티티](/creator/content-creator-ko/sdk7/architecture/entities-components.md#reserved-entities) `engine.CameraEntity`. 1인칭에서 카메라 엔티티를 사용할 때, 연결된 엔티티는 카메라의 움직임을 따라갑니다. 이는 무언가를 항상 화면에 유지하는 데 이상적입니다. 예를 들어 카메라가 위를 향해도 총의 3D 모델이 항상 보이도록 유지할 수 있습니다.

```ts
let childEntity = engine.addEntity()

MeshRenderer.setCylinder(childEntity)

Transform.create(childEntity, {
	scale: Vector3.create(0.2, 0.2, 0.2),
	position: Vector3.create(0, 0.4, 0),
	parent: engine.CameraEntity,
})
```

아바타의 뼈 중 하나에 오브젝트를 부착하고 아바타의 애니메이션과 함께 움직이게 하려면 다음을 추가합니다: `AvatarAttach` 컴포넌트를 엔티티에.

아바타에서 서로 다른 앵커 포인트를 선택할 수 있으며, 이러한 대부분의 포인트는 플레이어의 스켈레톤에 연결되어 플레이어의 애니메이션을 따라갑니다. 예를 들어 오른손 앵커 포인트를 사용하면, 연결된 엔티티는 플레이어가 달리면서 팔을 흔들거나 휘두를 때 손에 들고 있는 것처럼 움직입니다.

```ts
// 메인 플레이어에 연결, avatarId가 설정되지 않으면 기본적으로 engine.PlayerEntity 사용
AvatarAttach.create(myEntity, {
	anchorPointId: AvatarAnchorPointType.AAPT_NAME_TAG,
})

// ID로 플레이어에 연결
AvatarAttach.create(myEntity, {
	avatarId: '0xAAAAAAAAAAAAAAAAA',
	anchorPointId: AvatarAnchorPointType.AAPT_NAME_TAG,
})
```

다음을 생성할 때 `AvatarAttach` 컴포넌트에는 다음 데이터가 포함된 객체를 전달합니다:

* `avatarId`: *선택 사항* 연결할 플레이어의 ID입니다. 이 값은 이더리움 지갑으로 연결한 플레이어의 경우 플레이어의 이더리움 주소와 같습니다. 지정하지 않으면 엔티티는 로컬 플레이어의 아바타에 연결됩니다.
* `anchorPointId`: 열거형에서 값을 사용하여 엔티티를 아바타 스켈레톤의 어떤 앵커 포인트에 부착할지 지정합니다: `AvatarAnchorPointType`.

{% hint style="warning" %}
**📔 참고**: 씬의 모든 플레이어가 같은 플레이어에게 연결된 오브젝트를 보게 하려면, 예를 들어 모두가 플레이어 A가 오브젝트를 집어 왼손에 들고 있는 것을 보게 하려면, 다음에 값을 제공해야 합니다: `avatarId`. 지정하지 않으면 모든 플레이어는 자신의 아바타에 연결된 오브젝트를 보게 됩니다.
{% endhint %}

다음 예제는 특정 아바타에 연결된 엔티티를 배치하여, 다른 모든 플레이어가 그것이 같은 아바타에 연결된 것으로 보게 합니다.

```ts
import { getPlayer } from '@dcl/sdk/src/players'
import { AvatarAnchorPointType, AvatarAttach, engine, Entity } from '@dcl/sdk/ecs'
import { syncEntity } from '@dcl/sdk/network'

async function attachToPlayer(){

 let userData = await getPlayer()
 console.log(userData)

 if (!userData || !userData.wearables) return

  let entity = engine.addEntity()

  AvatarAttach.create(entity, {
    avatarId: userData.userId,
    anchorPointId: AvatarAnchorPointType.AAPT_RIGHT_HAND,
  })

  // 기타 컴포넌트

  syncEntity(entity, [AvatarAttach.componentId])

}
```

다음 앵커 포인트를 사용할 수 있습니다: `AvatarAnchorPointType` 열거형의 다음 값 중 하나입니다:

* `AAPT_RIGHT_HAND`: 플레이어의 오른손에 고정
* `AAPT_LEFT_HAND`: 플레이어의 왼손에 고정
* `AAPT_HEAD`: 플레이어 머리의 중심에 고정
* `AAPT_NECK`: 플레이어 목의 아래쪽에 고정
* `AAPT_SPINE`: 척추 상단 부분에 고정
* `AAPT_SPINE1`: 척추 중간 부분에 고정
* `AAPT_SPINE2`: 척추 하단 부분에 고정
* `AAPT_HIP`: 골반뼈에 고정
* `AAPT_LEFT_SHOULDER`: 왼쪽 어깨에 고정
* `AAPT_LEFT_ARM`: 왼쪽 첫 번째 팔뼈, 어깨 높이에 고정
* `AAPT_LEFT_FOREARM`: 왼쪽 아래팔뼈에 고정
* `AAPT_LEFT_HAND_INDEX`: 왼쪽 검지손가락 끝에 고정
* `AAPT_RIGHT_SHOULDER`: 오른쪽 어깨에 고정
* `AAPT_RIGHT_ARM`: 오른쪽 첫 번째 팔뼈, 어깨 높이에 고정
* `AAPT_RIGHT_FOREARM`: 오른쪽 아래팔뼈에 고정
* `AAPT_RIGHT_HAND_INDEX`: 오른쪽 검지손가락 끝에 고정
* `AAPT_LEFT_UP_LEG`: 왼쪽 다리의 허벅지뼈에 고정
* `AAPT_LEFT_LEG`: 왼쪽 다리의 정강이뼈에 고정
* `AAPT_LEFT_FOOT`: 왼쪽 발목에 고정
* `AAPT_LEFT_TOE_BASE`: 왼쪽 발가락 끝에 고정
* `AAPT_RIGHT_UP_LEG`: 오른쪽 다리의 허벅지뼈에 고정
* `AAPT_RIGHT_LEG`: 오른쪽 다리의 정강이뼈에 고정
* `AAPT_RIGHT_FOOT`: 오른쪽 발목에 고정
* `AAPT_RIGHT_TOE_BASE`: 오른쪽 발가락 끝에 고정
* `.AAPT_NAME_TAG`: 플레이어의 이름표 바로 위에 떠 있으며, 플레이어의 애니메이션의 영향을 받지 않습니다.

  > 참고: 이름표 높이는 플레이어가 착용한 착용 아이템의 높이에 따라 동적으로 조정됩니다. 따라서 키가 큰 모자를 쓴 플레이어의 이름표는 다른 플레이어보다 조금 더 높게 표시됩니다.
* `AAPT_POSITION` *사용 중단됨*: 플레이어의 전체 위치입니다. 이는 플레이어의 발에서 0.8 높이에 표시됩니다.

  >

{% hint style="warning" %}
\> \*\*📔 참고\*\*: \`AAPT\_POSITION\`은 사용 중단되었습니다. 플레이어의 전체 위치를 따라가려면 엔티티를 Avatar Entity의 자식으로 만드는 것이 가장 좋습니다. 예시는 이 섹션의 시작 부분을 참조하세요. >
{% endhint %}

{% hint style="info" %}
**💡 팁**: 이 값들을 사용하려면 다음과 같이 작성하세요 `AvatarAnchorPointType.` 그러면 VS Code에 드롭다운으로 전체 옵션 목록이 표시됩니다.
{% endhint %}

![](https://3980763956-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoPnXBby9S6MrsW83Y9qZ%2Fuploads%2Fgit-blob-206945bba419a58cd6fe54c557cc6e5d75e1bb86%2Favatar-attach-points.png?alt=media)

엔티티 렌더링은 씬의 각 인스턴스에서 로컬로 결정됩니다. 한 플레이어에게 엔티티를 연결해도, 그 플레이어를 보고 있는 다른 플레이어에게는 보이지 않습니다. 엔티티가 기본 로컬 플레이어에 연결되면, 각 플레이어는 그 엔티티를 자신의 아바타에 연결된 것으로 경험하게 됩니다.

{% hint style="warning" %}
**📔 참고**: 아바타에 연결된 엔티티는 렌더링되기 위해 씬 경계 안에 있어야 합니다. 플레이어가 씬 밖으로 나가면, 연결된 엔티티는 플레이어가 다시 들어올 때까지 렌더링이 중지됩니다. 스마트 웨어러블에는 이 제한이 없습니다.
{% endhint %}

그 `AvatarAttach` 컴포넌트가 다음의 값을 덮어씁니다 `Transform` 컴포넌트. 당신이 다음에 넣는 값은 `Transform` 컴포넌트는 엔티티의 플레이어 Transform에 대한 상대 위치로 대체되며, 플레이어가 움직이고 애니메이션할 때 이 값들은 프레임마다 업데이트됩니다.

아바타의 앵커 포인트에서 오프셋을 두거나 다른 회전 또는 스케일로 엔티티를 배치해야 한다면, 부모 엔티티를 통해 수행하세요.

1. 다음만 있는 보이지 않는 엔티티를 만드세요 `Transform` 그리고 하나의 `AvatarAttach` 컴포넌트. 그 `Transform` 값은 플레이어가 움직일 때 덮어씌워집니다
2. 연결하려는 엔티티를 이 부모의 자식으로 설정하세요. 그 `Transform` 값은 앵커 포인트로부터의 오프셋을 설명할 수 있습니다.

```ts
// 부모 엔티티 생성
const parentEntity = engine.addEntity()

// 부모 엔티티를 플레이어에 연결
AvatarAttach.create(parentEntity, {
	anchorPointId: AvatarAnchorPointType.AAPT_NAME_TAG,
})

// 자식 엔티티 생성
let childEntity = engine.addEntity()

MeshRenderer.setCylinder(childEntity)

Transform.create(childEntity, {
	scale: Vector3.create(0.2, 0.2, 0.2),
	position: Vector3.create(0, 0.4, 0),
	parent: parentEntity,
})
```

{% hint style="warning" %}
**📔 참고**: 연결된 엔티티에 콜라이더가 있으면, 이러한 콜라이더가 플레이어의 이동을 막거나 떨림 효과를 일으킬 수 있습니다. 연결된 엔티티의 콜라이더에 대해 물리 레이어를 비활성화하는 것이 좋을 수 있습니다. 다음을 참조하세요 [충돌 레이어](/creator/content-creator-ko/sdk7/3d/colliders.md#collision-layers)
{% endhint %}

{% hint style="warning" %}
**📔 참고**: 자식 엔티티가 있고 그 전역 Position 및/또는 Rotation을 알고 싶다면, 다음을 사용할 수 있습니다 `getWorldPosition` 및 `getWorldRotation` 함수들을 사용할 수 있습니다. 다음에서 확인할 수 있습니다: [전역 Position 및 Rotation 가져오기](#getting-global-position-and-rotation-of-an-entity) 섹션.
{% endhint %}

### 다른 플레이어에게 연결

다음을 사용할 수 있습니다. `AvatarAttach` 다른 플레이어에게 엔티티를 연결하려면 이 컴포넌트를 사용하세요. 이를 위해 플레이어의 id를 알아야 합니다.

다른 플레이어의 아바타에 엔티티를 연결하려면, 필드에 사용자의 ID를 입력해야 합니다 `avatarId`. [다양한 방법](/creator/content-creator-ko/sdk7/interactivity/user-data.md#get-player-data) 으로 이 데이터를 얻을 수 있습니다.

{% hint style="warning" %}
**📔 참고**: 이더리움 지갑으로 연결된 플레이어의 경우, 그들의 `userId` 는 이더리움 주소와 같습니다.
{% endhint %}

다음을 가져오세요 `userId` 를, 주변의 다른 모든 플레이어에 대해 다음을 통해: `getPlayer()`

```ts
executeTask(async () => {
	for (const [entity, data] of engine.getEntitiesWith(PlayerIdentityData)) {
		console.log('Player id: ', data.address)
	}
})
```

이를 다음과 함께 사용하면 `AvatarAttach`, 씬의 다른 모든 플레이어의 머리 위에 떠 있는 큐브를 추가하는 다음 코드를 사용할 수 있습니다:

```ts
executeTask(async () => {
        for (const [entity, data] of engine.getEntitiesWith(PlayerIdentityData)) {
            const myEntity = engine.addEntity()
            MeshRenderer.setBox(myEntity)
            AvatarAttach.create(myEntity, {
                anchorPointId: AvatarAnchorPointType.AAPT_LEFT_HAND,
                avatarId: data.address,
            })
        }
    })
```

다른 사용자의 ID를 가져오는 다른 방법은 다음에서 확인하세요: [플레이어 데이터 가져오기](/creator/content-creator-ko/sdk7/interactivity/user-data.md#get-player-data).

## 씬 경계

씬의 모든 엔티티는 씬 경계 안에 있어야 합니다. 그 경계 밖은 다른 플레이어가 소유한 토지 구획이기 때문입니다.

미리보기 실행 중 모델의 일부가 이러한 한계를 넘어 확장되면, 넘어간 부분은 잘려 나가 렌더링되지 않습니다. 이는 미리보기 실행 시와 게시된 씬 모두에서 동일합니다.

씬 안의 엔티티 위치는 이동할 때마다 계속 확인됩니다. 엔티티가 씬을 벗어났다가 다시 돌아오면 제거되었다가 다시 정상적으로 렌더링됩니다.

씬 바닥의 그리드는 씬의 경계를 보여주며, 기본적으로 *x* 및 *부터* 축에서 0에서 16까지, 그리고 *y* 축에서 최대 20까지입니다. 엔티티를 지하, 즉 다음 축에서 0보다 아래에 배치해도 됩니다 *y* 축입니다.

{% hint style="info" %}
**💡 팁**: 씬에 더 많은 구획이 필요하면 프로젝트의 `scene.json` 파일에 추가할 수 있습니다. 다음을 참조하세요 [씬 메타데이터](/creator/content-creator-ko/sdk7/kinds-of-projects/scene-metadata.md) 지침은 다음을 참조하세요. 추가하면 그리드가 확장되어 추가된 구획을 덮는 것을 볼 수 있습니다.
{% endhint %}


---

# 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-ko/sdk7/3d/entity-positioning.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.
