애니메이션이 실행되는 도중에 타이밍에 맞춰서 무언가가 실행되어야 하는 경우가 종종 발생합니다. 예를 들자면 대표적으로 캐릭터가 걷거나 뛸 때 발소리가 나거나 먼지가 일어나야 한다던지 캐릭터가 무기를 휘두를 때 맞는 타이밍에 맞춰서 데미지가 들어가야 한다던지 하는 경우가 있을 수 있다. 이러한 문제를 해결하는 하드한 방법으로는 계산해낸 타이밍에 맞춰서 해당 함수를 실행시킨다던지, 콜라이더를 원하는 위치에 붙여서 그 콜라이더가 충돌했을 때 처리하는 방법이 있자만, 이러한 방법들은 매우 비효율적이다.
그래서 존재하는 것이 바로 유니티의 애니메이션 이벤트(Animation Event)라는 기능이다. 이 기능은 애니메이션의 실행 도중, 원하는 시점에 원하는 함수를 호출할 수 있게 해준다.
방법으로는 2가지가 있다.
1. FBX 모델과 함께 임포트된 애니메이션에서 사용하는 방법
2. 애니메이션 클립(Animation Clip)에서 사용하는 방법
프로젝트 창(Project view)에서 임포트한 FBX파일을 선택하면 Inspector 창에 그 FBX파일의 정보들이 보일 것이다. 그 중에서 상단의 Animations라는 탭을 선택하면 그 FBX에 포함된 애니메이션의 정보를 볼 수 있다. 우리가 필요로 하는 애니메이션 이벤트 기능은 그 중에서 Events라는 곳 안에서 사용할 수 있다. 그 항목을 열면 다음과 같은 내용을 볼 수 있다.
앵커를 추가해주면 아래의 변수값이 활성화 되며 입력이 가능해집니다.
앵커는 드래그로 위치 조절이 가능합니다.
필드 이름 | 내용 |
---|---|
Function | 이벤트 시점에 실행될 함수의 이름 |
Float | 함수에 float형 매개변수가 있을 때 들어갈 값 |
Int | 함수에 int형 매개변수가 있을 때 들어갈 값 |
String | 함수에 string형 매개변수가 있을 때 들어갈 값 |
Object | 실행할 함수가 들어있는 스크립트 |
참고로 애니메이션 이벤트가 함수를 호출하는 방식은 여기에 넣어준 함수 이름으로 애니메이터 컴포넌트가 붙어있는 게임 오브젝트에 부착되어 있는 모든 컴포넌트에서 같은 이름을 가진 함수를 찾아서 실행하는 것이다.
만약 게임 오브젝트에 붙어있는 A라는 컴포넌트와 B라는 컴포넌트가 둘 다 Attack이라는 함수를 가지고 있다면 이 두 함수가 모두 호출된다.
애니메이션 뷰에서도 FBX파일의 애니메이션 이벤트와 같이 AddEvent 버튼을 볼 수 있는데 이것을 누르면 새로운 이벤트를 생성할 수 있다.
참고로 객체안에 애니메이션이 들어가있으며 그 객체 안에 스크립트로 public으로 선언된 매서드가 있으면 선택해서 참조할 수 있다.
이 애니메이션 이벤트는 굉장히 편리해보이지만 몇 가지 단점이 있어서 신중하게 사용해야 한다.
첫 번째 단점은 레거시(Legacy) 애니메이션을 사용할 때 프레임이 심하게 낮아지거나, 메카님 애니메이션에서 트랜지션을 설정할 때 블랜드되는 과정을 잘못 설정하면 애니메이션 이벤트가 실행되지 않는 경우가 발생할 수 있다.
이동할 때 먼지가 발생하는 수준의 기능이면 큰 문제가 되지 않겠지만, 앞에서 구현한 예시처럼 타이밍에 맞춰서 대미지를 넣는 기능을 애니메이션 이벤트로 만들었는데 이게 스킵되는 문제가 발생하면 게임에 심각한 영향을 미치게 된다.
두 번째 단점으로는 함수의 호출 구조를 파악하는게 어려워진다는 것이다.
스크립트 에디터에서 애니메이션 이벤트로 만든 함수를 보면 위쪽에 참조 0개라는 글자가 보인다. 이것은 이 함수를 전체 스크립트에서 몇 군데의 위치에서 호출하고 있는지를 알려준다
예를 들어서 Start 함수에서 이 Attack 함수를 호출하고 있다면 참조 0개가 참조 1개로 바뀌는 것을 볼 수 있다.
이 글자를 클릭해보면 어디서 호출되고 있는지 볼 수 있고 호출되고 있는 위치로도 바로 이동할 수도 있다.
게임에 버그가 발생했을 때는 이런 방식으로 호출 구조를 파악해서 흐름을 확인해야 하는 경우가 많은데 애니메이션 이벤트로 호출된 함수는 이 참조에 표시되지 않기 때문에 문제가 발생했을 때 문제가 발생한 지점을 찾기가 어려워 진다.
세 번째 단점은 네트워크 게임을 만들 때 애니메이션 이벤트를 사용하면 굉장히 곤란한 문제가 발생할 확률이 높다는 것이다.
공격과 대미지 타이밍 같은 처리는 굉장히 중요한 판정으로 분류되기 때문에 네트워크 게임에서는 주로 서버가 처리해야되는 작업인데 서버는 최적화가 굉장히 중요하기 때문에서 애니메이션 재생 같은 부분은 처리하지 않도록 하는 경우가 많다.
그렇게 최적화를 진행한 서버에서는 애니메이션 재생이 진행되지 않으니 애니메이션 이벤트 역시 실행되지 않을 것이다. 그렇기 때문에 네트워크 게임에서는 공격 타이밍과 관련된 방법을 애니메이션 이벤트가 아닌 다른 방법으로 구현해야 한다.
이 애니메이션 이벤트를 사용할 때, 프레임이 씹힐 경우에 애니메이션 이벤트가 같이 스킵되는 경우가 발생한다는 이야기도 있다. 다른 이야기로는 이 문제는 레거시(Legacy) 애니메이션을 사용할 때 주로 발생하며, 메카님에서는 개발자의 실수로 트랜지션 구간을 잘못 설정했을 때 발생하는 문제이며 일반적으로는 발생하지 않는 문제라고도 한다. 이런 문제가 발생하면 애니메이션의 트랜지션에서 블랜드되는 과정을 잘 확인해보는 것이 우선일 것 같다.