---
title: 애니메이션 이벤트 사용하기
slug: world-sdk-guide-kr/Dd4_xIS_23wnGvxXUBpoQ
docTags: 
createdAt: 2024-09-02T08:34:13.135Z
---

애니메이션 이벤트는 애니메이션 클립의 특정 시간에 사용자 정의 함수를 호출하거나 작업을 수행하는 방법을 제공합니다.

이는 애니메이션과 스크립트 간의 상호작용을 가능하게 하며, 애니메이션의 정확한 타이밍에 작업을 수행할 때 유용합니다.



### 객체 애니메이션에 이벤트 추가하기

다음 예제는 애니메이션 객체에 애니메이션 이벤트를 추가합니다.

이 구조는 위로 및 아래로 반복되는 애니메이션에 Up 이벤트와 Down 이벤트를 추가하여 이벤트가 실행될 때마다 정보를 콘솔 로그에 출력합니다.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-xO_1nL7IRhCFVsPcmwFGM-20240904-102422.gif" size="74" width="1310" height="864" position="center" showCaption="false"}



1\) 게임 오브젝트 > 3D 오브젝트 > 큐브를 선택하여 장면에 큐브를 생성합니다.

- 생성된 큐브를 선택하고 검사기 패널의 구성 요소 추가 버튼을 클릭하여 애니메이터 구성 요소를 추가합니다.
- 추가된 애니메이터에 큐브 애니메이터 컨트롤러를 적용합니다.
- 큐브 애니메이터 컨트롤러의 항목에 큐브 애니메이션 클립을 적용하여 장면이 재생될 때 큐브 애니메이션이 재생되도록 합니다.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-wMEQaupztsnprYFC5J74G-20240904-102422.png)



애니메이터 등록 및 애니메이션 클립 편집에 대한 다음 가이드를 참조하십시오.

:::hint{type="info"}
**📘 유니티 애니메이션 이벤트 가이드**
[https://docs.unity3d.com/kr/current/Manual/script-AnimationWindowEvent.html](https://docs.unity3d.com/kr/current/Manual/script-AnimationWindowEvent.html)
:::

:::hint{type="info"}
**📘 유니티 학습 애니메이션 튜토리얼**
[https://learn.unity.com/tutorial/may-18-animation?language=en#](https://learn.unity.com/tutorial/may-18-animation?language=en#)
:::



2\) 다음 속성을 큐브 애니메이션 클립에 추가하십시오.

- 큐브 애니메이션 클립의 0초, 2초 구간에 위치 (x: 0, y:0, z:0)의 키프레임이 있습니다.
- 큐브 애니메이션 클립의 1초 구간에 위치 (x: 0, y:1, z:0)의 키프레임이 있습니다.

(1) 큐브 애니메이션 클립의 1초 구간에 애니메이션 이벤트를 등록하십시오.

- 기능 : 호출
- 문자열 : 위

(2) 큐브 애니메이션 클립의 2초 구간에 애니메이션 이벤트를 등록하십시오.

- 기능 : 호출
- 문자열 : 아래

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-Yzu5ZqoYDS9lZKn-vpM9K-20240904-102422.png)



:::hint{type="success"}
- Unity에서 C#을 통해 애니메이션 이벤트를 작성할 때, 함수 이름을 Function에 작성하십시오.
- 그러나 TypeScript에서 애니메이션 이벤트를 호출하려면, Invoke는 Funtion에 작성해야 하며 함수 이름은 String, 인수 값으로 작성해야 합니다.
:::



3\) 프로젝트 생성 > 생성 > ZEPETO > TypeScript로 이름을 ObjectAnimationController로 변경합니다.

- 아래와 같이 샘플 스크립트를 작성하십시오.

:::CodeblockTabs
ObjectAnimationController.ts

```typescript
import { ZepetoScriptBehaviour } from 'ZEPETO.Script'

export default class ObjectAnimationController extends ZepetoScriptBehaviour {

    public Up() {
        console.log(`Cube is Up`);
    }

    public Down(){
        console.log(`Cube is Down`);
    }
}
```
:::

4\) 재생 버튼을 눌러 실행하면, 큐브의 애니메이션이 재생되는 동안 콘솔 로그 출력이 표시됩니다.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-nI5ZbpXCgO1e15p48DAX4-20240904-102422.gif)



### 로컬 캐릭터의 애니메이션 이벤트를 사용하여 발자국 소리를 재생합니다.

ZEPETO 캐릭터의 애니메이터에 애니메이션 이벤트를 추가하려면, 캐릭터가 생성될 때 런타임에서 이벤트를 추가해야 합니다.

다음 예제는 런타임에서 로컬 플레이어 애니메이터의 특정 애니메이션 클립에 이벤트를 적용하고, 이벤트가 발생할 때 발자국 소리를 재생합니다.

1\) 로컬 플레이어의 애니메이터 객체에 적용될 FootStepController 스크립트를 생성합니다. FootStepController는 애니메이터에 애니메이션 이벤트를 추가하는 역할을 합니다.

- 프로젝트 생성 > 생성 > ZEPETO > TypeScript로 이름을 FootStepController로 변경합니다.
- 아래와 같이 스크립트를 작성합니다.

:::CodeblockTabs
FootStepController.ts

```Text
import { AnimationEvent, Animator, AudioClip, AudioSource } from 'UnityEngine';
import { ZepetoScriptBehaviour } from 'ZEPETO.Script';

export default class FootStepController extends ZepetoScriptBehaviour {

    // 발자국 효과에 사용되는 소리
    public footStepSound: AudioClip;

    // 발자국 소리를 재생하기 위한 오디오 소스
    private _zepetoAudio: AudioSource;

    // 발자국 소리를 트리거하기 위해 애니메이션 이벤트를 추가합니다
    public AddAnimationEvent() {
        
        // 이 GameObject에 연결된 Animator 컴포넌트를 가져옵니다
        const anim = this.GetComponent<Animator>();

        // Animator 컴포넌트가 존재하는지 확인합니다
        if (anim != null) {
            // 발자국 소리를 위한 AudioSource를 생성합니다
            this.SetAudio();

            // 애니메이션 클립에서 발자국 소리가 재생되어야 하는 시간을 지정합니다
            const runSoundEventTimes = [0.1, 0.6];

            // 지정된 애니메이션 클립에 애니메이션 이벤트를 추가합니다
            this.AddAnimationClipEvent(anim, "move_walk", runSoundEventTimes);
        }
    }

    // 발자국 소리를 재생하기 위한 AudioSource를 설정합니다
    private SetAudio() {

        // AudioSource 컴포넌트를 생성하고 구성합니다
        this._zepetoAudio = this.gameObject.AddComponent<AudioSource>();
        this._zepetoAudio.clip = this.footStepSound;
    }

    // 발자국 소리를 활성화합니다
    public ActivateFootSteps() {

        // 발자국 소리가 재생되고 있음을 나타내는 로그 메시지를 출력합니다
        console.log("FootSteps!");

        // 구성된 AudioSource를 사용하여 발자국 소리를 재생합니다
        this._zepetoAudio.Play();
    }

    // 지정된 애니메이션 클립에 애니메이션 이벤트를 추가합니다
    private AddAnimationClipEvent(anim: Animator, clipName: string, eventTimes: number[]) {

        // 애니메이션 클립의 인덱스를 초기화합니다
        let animationClipIndex: number;

        // runtimeAnimatorController에서 모든 애니메이션 클립을 가져옵니다
        const clips = anim.runtimeAnimatorController.animationClips;

        // 지정된 애니메이션 클립의 인덱스를 찾습니다
        for (let i = 0; i < clips.length; i++) {
            if (clips[i].name == clipName) {
                animationClipIndex = i;
            }
        }

        // 지정된 이벤트 시간을 반복합니다
        eventTimes.forEach(eventTime => {

            // 발자국 소리 트리거를 위한 새로운 AnimationEvent를 생성합니다
            const newEvent: AnimationEvent = new AnimationEvent();
            newEvent.time = eventTime;
            newEvent.functionName = "Invoke";
            newEvent.stringParameter = "ActivateFootSteps";

            // 애니메이션 클립에 새로운 AnimationEvent를 추가합니다
            clips[animationClipIndex].AddEvent(newEvent);
        });
    }
}
```
:::

- 스크립트 설명
  - FootStepController는 애니메이션 이벤트를 추가하고 해당 이벤트가 발생할 때 발자국 사운드 효과를 재생합니다.
  - SetAudio()는 오디오 소스 컴포넌트를 추가하여 발자국 소리를 객체에 적용합니다.
  - AddAnimationClipEvent()는 지정된 애니메이션 클립에 애니메이션 이벤트를 추가합니다. 다음 요소들을 인수 값으로 넣어야 합니다.
    - 로컬 플레이어용 애니메이터
    - 이벤트가 적용되는 애니메이션 클립 이름
    - 이벤트를 적용할 애니메이션 시간의 배열
- AddAnimationClipEvent()로 등록된 newEvent에서 다음 항목이 설정됩니다.

(1) newEvent.time : 이벤트가 발생할 때의 애니메이션 시간. 값이 0이면 전체 길이의 시작이고, 값이 1이면 전체 길이의 끝입니다.

(2) newEvent.functionName : 이벤트가 발생할 때 호출되는 함수의 이름. TypeScript에서는 "Invoke"로 타입을 지정해야 합니다.

(3) newEvent.stringParameter : 이벤트가 함수를 실행할 때 함수에 설정되는 매개변수 값. TypeScript는 실행될 함수의 이름을 나열합니다.

- 이벤트가 발생하면 ActivateFootSteps()가 실행되고 발자국 소리가 재생됩니다.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-PQibq7pcRcM2_Iwp6BIwW-20240904-102422.png)



2\) 이제 로컬 플레이어가 런타임에 생성될 때 로컬 플레이어의 Animator 객체에 FootStepController 구성 요소를 추가하는 FootStepManager를 생성합니다.

- 프로젝트 > 생성 > ZEPETO > TypeScript로 이름을 FootStepManager로 변경합니다.
- 스크립트를 아래와 같이 작성합니다.

:::CodeblockTabs
FootStepManager.ts

```Text
import { SpawnInfo, ZepetoPlayers } from 'ZEPETO.Character.Controller'
import { ZepetoScriptBehaviour } from 'ZEPETO.Script'
import FootStepController from './FootStepController'
import { WorldService } from 'ZEPETO.World'
import { AudioClip } from 'UnityEngine';

export default class FootStepManager extends ZepetoScriptBehaviour {

    // 발소리를 재생할 사운드
    public footStepSound: AudioClip;

    Start() {

        // 로컬 플레이어가 추가될 때의 이벤트 리스너
        ZepetoPlayers.instance.OnAddedLocalPlayer.AddListener(() => {

            // 로컬 플레이어의 Zepeto 캐릭터에 접근
            const zepetoCharacter = ZepetoPlayers.instance.LocalPlayer.zepetoPlayer.character;

            // ZepetoAnimator의 GameObject에 FootStepController 스크립트를 추가
            const footStepController = zepetoCharacter.ZepetoAnimator.gameObject.AddComponent<FootStepController>();

            // FootStepController에 footStepSound 설정
            footStepController.footStepSound = this.footStepSound;

            // 발소리를 재생하기 위한 애니메이션 이벤트 추가
            footStepController.AddAnimationEvent();

        });
    }

}
```
:::

- 스크립트 설명
  - FootStepManager가 로컬 플레이어가 추가되고 있음을 감지하면, 플레이어의 ZepetoAnimator의 GameObject에 FootStepController 스크립트를 부착합니다.
  - FootStepController는 발소리를 재생하는 애니메이션 이벤트를 추가하는 역할을 합니다.

:::hint{type="success"}
* 애니메이션 이벤트에 의해 실행되는 함수의 스크립트는 해당 Animator 컴포넌트가 적용된 객체에 동일하게 적용되어야 합니다.
* 따라서 ZepetoAnimator.gameObject를 찾아 FootStepController 스크립트를 AddComponent로 적용해야 합니다.
:::



3\) FootStepManager의 footStepSound에 발소리를 적용합니다.

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-xzBMK0F7JDaBCBNoarBm0-20240904-102422.png)



4\) 재생 버튼을 눌러 실행하면, 로컬 플레이어가 걸을 때마다 그에 따라 소리가 재생되는 것을 볼 수 있습니다.

::Image[]{src="https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-sOZL6vMX48bJ25maFSkLR-20240904-102423.gif" size="70" width="1328" height="745" position="center" showCaption="false"}



:::hint{type="success"}
**👍 팁**

- ZEPETO 기본 애니메이터의 걷기 상태는 여러 애니메이션 블렌드와 상태로 구성됩니다.
- 예제는 move\_walk 상태에만 소리를 적용하므로 AddAnimationClipEvent()를 사용자 정의하고 빠른 걷기 및 달리기와 같은 상태에 직접 입력할 수 있습니다.
- 여러 애니메이션 상태에 소리가 적용될 때 애니메이션 블렌드로 인해 발소리가 겹칠 수 있습니다. 이를 해결하기 위해 AnimationEvent.animatorClipInfo.weight가 0.5일 때 해당 소리가 재생되도록 추가 조건문을 작성하세요.
:::

:::hint{type="danger"}
**❗️ 알려진 문제**

- 개발 가이드 스타일에 따라 구현할 경우 다음과 같은 오류 메시지가 나타날 수 있지만 실행에는 문제가 없어야 합니다.
:::

![](https://api.archbee.com/api/optimize/fCt3n1oCa8rgNJ8fw9I2N-233nZRPAw731S17OMHzra-20240904-102422.png)



