> 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/avatars/avatar-animations.md).

# 아바타 애니메이션

플레이어의 아바타가 기본 또는 사용자 지정 애니메이션을 재생하도록 하고, 이모트가 끝나는 시점을 감지합니다

씬의 코드의 일부로 플레이어가 애니메이션을 수행하도록 만들 수 있습니다. 이는 더 높은 몰입감을 제공하는 데 도움이 되며, 다른 플레이어들이 서로 무엇을 하고 있는지 전달하는 데도 도움이 됩니다. 아바타 애니메이션은 플레이어 자신(3인칭 시점)과 주변의 다른 모든 플레이어에게 보입니다.

플레이어가 제어하는 전신 애니메이션은 걷기나 점프 같은 기본 이동 애니메이션에 의해 덮어써집니다. 따라서 씬에서 재생되는 전신 애니메이션은 플레이어가 가만히 서 있을 때만 재생됩니다. 플레이어가 걷거나 점프하면 전신 애니메이션은 중단됩니다. 상체 애니메이션은 움직임으로 중단되지 않습니다.

{% hint style="warning" %}
**📔 참고**: 플레이어는 이웃한 씬에 있는 경우가 아니라, 이미 씬의 경계 안에 서 있는 경우에만 애니메이션을 적용할 수 있습니다. 스마트 웨어러블은 어디서나 애니메이션을 재생할 수 있습니다.

플레이어가 애니메이션을 수행하는 동안에는 충돌의 영향을 받지 않으며, 이동이 씬의 물리 규칙에 의해 제한되지 않습니다. 또한 애니메이션이 플레이어를 원래 위치에서 이동시키는 경우(예: 애니메이션에 점프가 포함된 경우), 플레이어의 Transform 컴포넌트는 이 이동의 영향을 받지 않습니다.
{% endhint %}

### 씬 에디터를 사용하세요

플레이어가 애니메이션을 수행하게 만드는 가장 쉬운 방법은 Scene Editor를 사용하는 것입니다. 노코드 **이모트 재생** 액션으로 기본 애니메이션을 재생하거나 **사용자 지정 이모트 재생** 액션으로 파일에서 애니메이션을 재생합니다. 다음을 참조하세요. [모든 항목을 스마트 아이템으로 만들기](/creator/content-creator-ko/scene-editor/interactivity/make-any-item-smart.md).

### 기본 애니메이션

다음을 사용하세요 `triggerEmote()` Decentraland 어디서나 플레이어가 재생할 수 있는 기본 애니메이션 중 하나를 실행하는 함수입니다. 이 함수는 다음 속성을 가진 객체를 인자로 받습니다:

* `predefinedEmote`: 기존 이모트의 문자열 이름입니다.
* `mask`: (선택 사항) 다음 값 중 하나를 사용하여 아바타 신체의 일부에만 애니메이션을 재생합니다. `AvatarMask` 열거형입니다. 예를 들면, `AvatarMask.AM_UPPER_BODY` 아바타의 상체만 애니메이션 처리합니다. 다음을 참조하세요. [상체만 애니메이션 처리](#animate-only-the-upper-body).

```ts
import { triggerEmote } from '~system/RestrictedActions'

const emoter = engine.addEntity()
Transform.create(emoter, { position: Vector3.create(8, 0, 8) })
MeshRenderer.setBox(emoter)
MeshCollider.setBox(emoter)
pointerEventsSystem.onPointerDown(
	{
		entity: emoter,
		opts: { button: InputAction.IA_POINTER, hoverText: 'Dance' },
	},
	() => {
		triggerEmote({ predefinedEmote: 'robot' })
	}
)
```

다음 이모트는 씬에서 플레이어의 행동에 대한 피드백을 보여주며, 이 모든 항목은 다음의 유효한 값입니다: `predefinedEmote` 필드:

* `buttonDown`
* `buttonFront`
* `getHit`
* `knockOut`
* `lever`
* `openChest`
* `openDoor`
* `punch`
* `push`
* `swingWeaponOneHand`
* `swingWeaponTwoHands`
* `throw`
* `sittingChair1`
* `sittingChair2`
* `sittingGround1`
* `sittingGround2`

이 이모트들은 기본 이모트 휠에서 모든 플레이어가 사용할 수 있으며, 어떤 씬에서든 사용할 수도 있습니다.

* `wave`
* `fistpump`
* `robot`
* `raiseHand`
* `clap`
* `money`
* `kiss`
* `tik`
* `hammer`
* `tektonik`
* `dontsee`
* `handsair`
* `shrug`
* `disco`
* `dab`
* `headexplode`

{% hint style="info" %}
**💡 팁**: 플레이어가 애니메이션을 재생하는 동안 걷거나 점프하면 애니메이션이 중단됩니다. 이를 원치 않는다면 다음을 사용해 아바타를 고정할 수 있습니다. [입력 수정자](/creator/content-creator-ko/sdk7/interactivity/avatars/locomotion.md#freeze-the-player) 아바타 애니메이션이 재생되는 동안.
{% endhint %}

### 사용자 지정 애니메이션

다음을 사용하세요 `triggerSceneEmote()` 를 사용하면 플레이어가 사용자 지정 애니메이션을 수행하게 만들 수 있으며, 이는 씬 자산의 일부로 .glb 파일로 저장됩니다.

{% hint style="warning" %}
**📔 참고**: 파일 이름은 **반드시** 다음으로 끝나야 합니다 `_emote.glb` 아바타 애니메이션으로 작동해야 합니다.
{% endhint %}

이 함수는 다음 속성을 가진 객체를 인자로 받습니다:

* `src`: 이모트 파일 경로를 담은 문자열입니다.
* `loop`: true이면 플레이어가 움직이거나 애니메이션이 중지될 때까지 애니메이션이 계속 반복됩니다. 기본값은 false입니다.
* `mask`: (선택 사항) 다음 값 중 하나를 사용하여 아바타 신체의 일부에만 애니메이션을 재생합니다. `AvatarMask` 열거형입니다. 예를 들면, `AvatarMask.AM_UPPER_BODY` 아바타의 상체만 애니메이션 처리합니다. 다음을 참조하세요. [상체만 애니메이션 처리](#animate-only-the-upper-body).

```ts
import { triggerSceneEmote } from '~system/RestrictedActions'
import { AvatarMask } from '@dcl/sdk/ecs'

const emoter = engine.addEntity()
Transform.create(emoter, { position: Vector3.create(8, 0, 8) })
MeshRenderer.setBox(emoter)
MeshCollider.setBox(emoter)
pointerEventsSystem.onPointerDown(
	{
		entity: emoter,
		opts: { button: InputAction.IA_POINTER, hoverText: 'Make snowball' },
	},
	() => {
		triggerSceneEmote({ src: 'animations/Snowball_Throw_emote.glb', loop: false, mask: AvatarMask.AM_UPPER_BODY })
	}
)
```

{% hint style="info" %}
**💡 팁**: 플레이어가 애니메이션을 재생하는 동안 걷거나 점프하면 애니메이션이 중단됩니다. 이를 원치 않는다면 다음을 사용해 아바타를 고정할 수 있습니다. [입력 수정자](/creator/content-creator-ko/sdk7/interactivity/avatars/locomotion.md#freeze-the-player) 아바타 애니메이션이 재생되는 동안.
{% endhint %}

### 상체만 애니메이션 처리

둘 다 `triggerEmote()` 과 `triggerSceneEmote()` 선택적 `mask` 속성을 받을 수 있으며, 이를 통해 애니메이션을 아바타 신체의 일부에만 제한할 수 있습니다.

일반적으로 애니메이션은 플레이어가 걷거나 점프하는 즉시 중단됩니다. 이는 기본 이동 애니메이션이 전신을 차지하기 때문입니다. 다음을 설정하면 `mask` 를 `AvatarMask.AM_UPPER_BODY`, 애니메이션은 아바타의 허리 위 부분만 제어하고 다리는 기본 이동 애니메이션이 계속 제어합니다. 즉, 플레이어는 상체에서 애니메이션이 재생되는 동안에도 씬을 계속 걷거나 뛰어다닐 수 있습니다. 상자를 들고 있거나, 횃불을 들고 있거나, 저글링하는 것처럼 움직임을 중단시키지 않아야 하는 동작에 사용하세요.

```ts
import { triggerSceneEmote } from '~system/RestrictedActions'
import {
	engine,
	AvatarMask,
	InputAction,
	MeshCollider,
	MeshRenderer,
	pointerEventsSystem,
	Transform,
} from '@dcl/sdk/ecs'
import { Vector3 } from '@dcl/sdk/math'

const cheerButton = engine.addEntity()
Transform.create(cheerButton, { position: Vector3.create(8, 0, 8) })
MeshRenderer.setBox(cheerButton)
MeshCollider.setBox(cheerButton)
pointerEventsSystem.onPointerDown(
	{
		entity: cheerButton,
		opts: { button: InputAction.IA_POINTER, hoverText: 'Cheer' },
	},
	() => {
		triggerSceneEmote({
			src: 'animations/Cheer_emote.glb',
			loop: true,
			mask: AvatarMask.AM_UPPER_BODY,
		})
	}
)
```

이 예시에서는 플레이어가 버튼을 클릭하면 반복 애니메이션으로 팔을 들어 올린 채 환호를 시작합니다. 상체만 애니메이션되므로, 예를 들어 경주나 축구 경기의 진행을 따라가면서 환호하는 동안에도 씬을 계속 뛰어다닐 수 있습니다.

유의할 사항:

* `AvatarMask.AM_UPPER_BODY` 은 현재 다음의 유일한 값입니다: `AvatarMask` 열거형. 전신 애니메이션을 재생하려면 단순히 다음을 설정하지 마세요: `mask` 속성으로 정의됩니다.
* 이 `loop` 속성은 전신 애니메이션과 동일하게 동작합니다. 즉, `loop: false` 마스킹된 애니메이션은 한 번 재생되고, 그다음 상체는 일반 이동 동작으로 돌아갑니다. 반면 `loop: true` 이것은 중지될 때까지 반복됩니다.
* 코드에서 반복되는 마스킹 애니메이션을 중지하려면 다음을 호출하세요: `stopEmote({})`, 역시 다음에서 가져옵니다 `~system/RestrictedActions`.

### 이모트가 끝나는 시점 감지

모든 이모트 수명 주기 이벤트는 다음을 통해 보고됩니다: `AvatarEmoteCommand` 플레이어 엔티티의 컴포넌트. 각 새 항목에는 다음이 포함됩니다: `state` 필드, 값은 다음의 값 중 하나입니다: `EmoteState` 열거형에서 사용할 수 있습니다:

* `EmoteState.ES_STARTED`: 이모트 재생이 시작되었습니다. 또한 다음이 `state` 필드가 없을 때(이전 클라이언트가 기록한 항목) 보고되는 값이기도 합니다.
* `EmoteState.ES_FINISHED`: 반복되지 않는 이모트가 자연스럽게 끝까지 재생되었습니다.
* `EmoteState.ES_INTERRUPTED`: 이모트가 중간에 끊겼습니다. 플레이어가 이동하거나 점프했거나, 텔레포트했거나, 다른 이모트가 시작되었거나, 이모트가 명시적으로 중지되었거나, 플레이어가 씬을 떠났습니다.

이는 씬에서 트리거된 이모트(`triggerEmote()` 과 `triggerSceneEmote()`)뿐 아니라 플레이어가 이모트 휠을 통해 직접 재생하는 이모트와 씬의 다른 플레이어가 재생한 이모트에도 적용됩니다.

다음을 사용하세요 `onChange` 다음의 함수 `AvatarEmoteCommand` 컴포넌트를 사용해 각 새 항목에 반응하세요:

```ts
import { AvatarEmoteCommand, EmoteState } from '@dcl/sdk/ecs'

export function main() {
	AvatarEmoteCommand.onChange(engine.PlayerEntity, (emote) => {
		if (!emote) return

		switch (emote.state ?? EmoteState.ES_STARTED) {
			case EmoteState.ES_STARTED:
				console.log('emote started: ', emote.emoteUrn)
				break
			case EmoteState.ES_FINISHED:
				console.log('emote finished naturally: ', emote.emoteUrn)
				break
			case EmoteState.ES_INTERRUPTED:
				console.log('emote was interrupted: ', emote.emoteUrn)
				break
		}
	})
}
```

{% hint style="warning" %}
**📔 참고**: 이 기능은 데스크톱 클라이언트에서만 지원됩니다. 다음을 사용해 재생된 이모트는 `mask` (부분 신체 이모트)는 현재 로컬 플레이어에 대해 수명 주기 이벤트를 보고하지 않습니다.
{% endhint %}

{% hint style="info" %}
**💡 팁**: 플레이어가 아닌 아바타에 애니메이션을 재생하려면 다음을 참조하세요. [NPC 아바타](/creator/content-creator-ko/sdk7/interactivity/avatars/npc-avatars.md#animations).
{% 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 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/avatars/avatar-animations.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.
