애니메이션은 게임에서 캐릭터 또는 적이 마치 살아 있는 듯하게 보이도록 하는 것으로 개발과정에서 중요한 파트입니다. 스크립트를 통해 아무 변화가 없는 이미지의 이동은 게임답지 못하기 때문인데요. 게임이 시작되면 게임 캐릭터나 적에게 여러가지 동작변화를 주어야 게임처럼 보입니다.
애니메이션에는 2D와 3D가 있지만 여기서는 2D 애니메이션 만드는 방법을 다루겠습니다. 애니메이션을 만드는 방법은 다음 3가지가 있습니다.
1. 프레임 바이 프레임 애니메이션:
고전 방식이며, 오래된 2D 게임에서 사용하는 방법이지만 다양한 동작을 표현하는데는 이 방식밖에는 없습니다. 캐릭터의 동작이 매우 다양한 격투 게임이 대표적인 예입니다. 기술 공격이 매우 다양할 뿐만 아니라 그 표현을 매우 화려하게 만들기 때문에 이 방식을 사용합니다. 탑다운뷰 또는 횡스크롤뷰 게임에서도 사용하지만 격투 장르 게임보다는 상대적으로 간단한 표현을 사용합니다. 이 방식은 한 장, 한 장을 연속적으로 연출하는 고전 방식이어서 표현이 다채로운 장점인 반면에 한 장, 한 장을 모두 그려 나가야 하기 때문에 비용면에서 좋지 않습니다. 물론 간단한 이미지라면 그려나가는 시간을 줄일 수도 있습니다. 애니메이션 아틀라스 한 장에 다양한 동작의 캐릭터 모습이 있습니다.
2. 컷아웃
주로 2D횡스크롤 방식에서 사용합니다. 왜냐하면 이 방식은 캐릭터의 측면을 보여주는 것이 애니메이션으로 만들기 유리하기 때문입니다. 컷아웃 방식은 우선 캐릭터를 그린 후에 캐릭터의 머리, 몸통, 오른쪽 팔, 왼쪽 팔, 오른쪽 다리, 왼쪽 다리로 파츠를 나누어서 아틀라스에 담고, 각 파트를 모아서 캐릭터로 만듭니다. 움직임은 각 파츠가 축(pivot)을 중심으로 회전을 통해 구현하는데 애니메이션 중 파츠를 변경해서 애니메이션을 만들기도 합니다. 단순한 파츠 위주로 애니메이션을 만들기 때문에 주로 단순한 캐릭터의 애니메이션을 만들 때 적합하고, 간단한 애니메이션에 주로 사용하기 때문에 제작 시 비용이 크게 들지 않는 장점이 있습니다. 그래서 캐릭터가 주로 옆으로 이동하면서 달리기, 점프, 공격, 죽음 등의 애니메이션 등 동작이 단순한 것에 집중되어 있습니다. 만약 사다리를 타야 한다면 캐릭터의 뒷통수, 뒷모습 등에 대한 파츠도 준비가 되어야 하니 좀 더 복잡해질 수 있습니다. 이럴 경우에는 그냥 프레임 바이 프레임을 사용합니다.
3. 골격 애니메이션
2D에서 매우 부드러우면서도 물리적 효과로 인한 애니메이션까지 줄 수 있는 방법입니다. 이 방식은 아틀라스의 스프라이트를 애니메이션 골격에 매핑해서 움직여주는 방식입니다. 골격은 말 그대로 뼈대를 말하기 때문에 bone animation 또는 spine animation이라고도 부릅니다. 실제 움직임은 골격(뼈)이 움직이는 것이고, 골격에 매핑된 각 스프라이트가 골격을 따라 움직이는 방식입니다. 매핑된 파츠는 weghts(무게)를 갖게 되는데 이를 활용해서 물리적 움직임도 줄 수 있습니다. 예를 들어 묶은 머리에 골격을 주고 매핑한 후 해당 파츠에 무게 설정을 주면 움직일 때 물리적 영향을 받아서 보여지게 됩니다. 이 외에도 스프라이트를 늘리고 줄일 수 있어서 과한 정도가 아니라면 자연스러움 숨쉬기 동작이나 가벼운 옷 펄럭임 착시도 줄 수 있습니다. 컷아웃과 비슷한 듯 하지만 좀 더 캐릭터 애니메이션을 부드럽고 섬세하게 표현을 해주기 때문에 많이 사용하는 애니메이션입니다. 그러나 이 방식은 애니메이션 제작이 쉽지 않은 방식으로 골격 애니메이션을 많이 다뤄본 경험이 풍부한 제작자가 하는 것을 추천합니다. 골격을 움직이면서 각 애니메이션 프레임을 만드는데 경험이 부족하면 정말 어렵기 때문입니다.
지금 만들어보는 게임에서는 프레임 바이 프레임 애니메이션 방식을 사용할 것이며, 시간 절약을 위해 네모난 robot 캐릭터에 표정 변화만 있는 애니메이션을 적용시키겠습니다. 애니메이션에 필요한 캐릭터 그림은 직접 그려도 되고, 애셋스토어를 활용해도 됩니다. 저는 단순한 로봇 캐릭터를 그려서 아틀라스로 만들기 위해 한 장에 여기저기 배치해 보았습니다. 해당 아틀라스 리소스는 그림툴에서 그린 후 PSD로 저장해서 유니티에 적용했습니다. 이 방법을 사용하려면 PSD importer가 있어야 합니다. 애셋스토어를 통해서 설치하시면 됩니다.
PSD importer 설치 후 적용방법
1. 유니티 project뷰에서 마우스 우클릭 creat-folder 생성 후 폴더명을 resource로 변경
2. 그림툴로 그림을 그린 후 저장 폴더는 'UnityProject 폴더'를 찾아야 합니다. 저장 시 PSD로 저장할 것
D:\UnityProject\ExampleProject\Assets\Resource (저의 경우)
그림을 적용한 후 유니티의 resource 폴더에 가보면 PSD로 저장되어 있는 것을 확인할 수 있습니다. 클릭해서 아틀라스를 열고 각 파츠를 슬라이스시켜줍니다. 위 그림에서 필요한 그림이 필요하다면 그림툴에서 해당 파일을 열고 빈 공간에 그림을 추가한 후 저장을 누르고 유니티로 돌아오면 리소스를 변경 및 적용합니다. 게임 배경 그림 그릴때 편리한데요. UI나 애니메이션에서는 유의해야할 부분이 있습니다. 제 경험상 겪었던 부분입니다.
1. 아틀라스에 있는 그림들은 하나의 그룹입니다. 그룹을 각 그림 별로 세분화할 때 순번이 있는데 좌측상단에서 우측하단으로 내려오는 순서로 매깁니다.
2. 그림을 툴에서 그릴 때 매끄럽게 그려야 합니다. 지우개로 잘 안 지워졌던 부분의 '점'까지 스프라이트가 슬라이싱 됩니다. PSD에서 벡터를 활용하고 벡터 지우개로 깨끗하게 지우고 그리는 것이 중요합니다.
게임 중간에 새로운 기능을 넣고 새로운 동작을 부여하고 싶어서 해당 아틀라스 빈 공간에 그림들을 채우고 다시 슬라이싱하면 어떤 결과가 벌어냐하면 기존에 적용한 캐릭터 애니메이션, UI, 배경 등의 스프라이트가 엉망이 됩니다. 배경에 캐릭터 얼굴 파트가 있고, 웃는 표정에 배경 그림이 중간에 튀어 나오는 등 전반적으로 리소스가 꼬이게 됩니다. 문제를 바로잡기에 시간이 많이 소요될 경우에는 아예 아틀라스를 새로 만들어서 사용하는 것이 좋습니다. 다만 아틀라스를 너무 많이 만들어서 사용하는 것은 최적화에 안 좋은 것이니 깔끔하게 써야 합니다.
그래서 첫시간 때 썼던 기획단계가 중요한 것입니다. 물론 게임을 만드는 도중에 수정하고 추가할 수도 있으나 조심해야 할 부분들이 있기 때문에 첫 단추부터 잘 채우는 것이 좋습니다. 게임에 필요한 기능과 동작들에 대한 세밀한 기획이 이런 시행착오를 줄일 수 있는데 도움을 줍니다.
애니메이션 적용 방법
리소스까지 준비가 되었다면 애니메이션을 만드는 것입니다. 먼저 project뷰에서 마우스 우클릭 후 animation폴더를 만들어 줍니다. 그 다음 애니메이션을 적용시킬 캐릭터 오브젝트를 클릭한 상태에서 유니티 상단 메뉴바 Window-Animation-Animation을 클릭하거나 항상 익히길 강조하는 기능인 핫키기능 Ctrl+6을 눌러줍니다. 애니메이션 창이 나오는데 creat 버튼을 누르고 anim형식의 애니메이션 컨트롤러를 만들어줍니다. 애니메이션 컨트롤러는 animator로써 캐릭터의 여러가지 animation clip들을 관리하는 역할을 합니다. 클립을 만들기 전에 캐릭터의 애니메이션 상태 동작에 대해 간략하게 알아보겠습니다.
캐릭터 애니메이션에는 Idle, Run, Attack, SpecialAttack, Jump, Damaged, Die 등을 애니메이션 클립으로 사용하지만 여기서는 애니메이션의 간소화를 위해서 Idle, Collision 정도로 클립을 만들겠습니다. Idle은 캐릭터의 이동이 없을 때 캐릭터 애니메이션으로 대부분 숨쉬는 동작을 하지만 컨셉이 robot이기 때문에 이렇게 할 수는 없고 해서 robot 디스플레이 패널에 표정을 넣고 이를 통해서 아주 간단한 애니메이션을 주고자 했습니다. Idle clip 상태를 눈깜빡이는 애니메이션으로 만들어서 적용해보겠습니다(Idle=Blink).
본론으로 돌아와서 애니메이션 클립을 만듭니다.
그림에서 보이는 Blink 옆 삼각형을 클릭하고 creat clip을 클릭하면 애니메이션 클릭명을 정하고 애니메이션 폴더에 저장합니다. 이때 클립명은 아무거나 써도 상관없지만 가급적 캐릭터 상태에 따른 명칭이 좋습니다. Idle, Attack, Run 등으로 클립명을 저장하면 애니메이션 적용 시 헷갈리지 않습니다.
1. 클립을 만든 후에 그림에서 보이는 빨간 버튼을 눌러서 키프레임 레코딩 모드를 켭니다.
2. 아틀라스에서 스프라이트를 드래그로 끌어와서 애니메이션 창에 떨어뜨려 줍니다.
3. 애니메이션 순서에 알맞게 배치를 하고 삼각형 플레이 버튼을 눌러서 애니메이션을 확인합니다.
4. Blink는 반복적 애니메이션이므로 loop로 계속 돌려야 하기 때문에 project뷰에서 생성한 애니메이션 폴더에서 Blink clip클릭 후 loop 체크박스를 해줍니다. 참고로 attack 같은 단일적 표현은 loop를 해제해 줘야 합니다.
이와 같은 방법으로 다른 애니메이션 클립을 만들어줍니다.
게임 화면으로 돌아와서 캐릭터를 클릭해 보면 자동으로 animator 컴포넌트가 추가되어 있고 아까 생성한 animator controller가 적용되어 있는 것을 확인할 수 있습니다.
이제 animator를 설정해서 clip들을 움직임에 맞게 control 해줄 차례입니다. 캐릭터가 선택된 상태에서 유니티 상단 Window-Animation-Animator를 클릭해줍니다.
Entry에서 오른쪽으로 향하는 주황색 화살선이 기본 시작선입니다. Entry에 마우스 우클릭하면 Set StateMachine default state를 클릭해서 Blink에 연결해줍니다. 시작하면서 바로 Blink 애니메이션을 작동하도록 합니다. 그림에서는 애니메이션 클립이 2개이기 때문에 두개만 세팅해보겠습니다. Blink clip과 Collision clip을 각각 우클릭하면 메뉴가 나오는데 Make transition을 눌러주게 되면 흰색 화살표선이 나타나는데 연결하고자 하는 클립에 대고 좌클릭하면 연결됩니다. 각 클릭이 상호 교류하는 애니메이션이라면 양방향을 설정해 주지만 아니라면 일방향만 설정합니다. 이 게임은 충돌하면 바로 게임오버이기 때문에 다시 Blink상태로 되돌아 올 필요가 없어서 일방향만 설정했습니다.
이제 파라미터를 만들어서 스크립트에서 써야합니다. animator창을 잘 보면 좌측 상단에 Parameters라는 탭이 있습니다. 클릭하면 List is Empty가 있고 +버튼이 있는데 클릭하면 float, int, bool, trigger 타입의 파라미터 선택지가 나옵니다. 대부분은 true, false로 판명하는 bool 타입 파라미터를 사용합니다. 파라미터 이름은 알아서 적는데 충돌여부를 체크해보는 것이니 isCollision으로 씁니다. 이 파라미터명은 캐릭터 컨트롤러 스크립트에서 사용됩니다.
Blink에서 Collision으로 향하는 흰색선을 클릭하면 inspector뷰에 애니메이션 설정창이 뜹니다.
Has Exit Time: 이 기능은 먼저 실행되는 애니메이션이 끝날 때 다음 애니메이션을 실행하게 합니다.
이 게임은 간단하고 단순한 애니메이션이기 때문에 애니메이션 블렌디드(두 클릭 교차부위의 자연스러운 전환)가 필요없습니다. 따라서 체크해제합니다.
중요한 것은 밑에 Conditions에서 +버튼을 눌러주면 아까 만든 파라미터명과 함께 true or false로 변경가능한 옵션창이 나옵니다. 스크립트에서 Collision 애니메이션 발생 조건이 벽에 충돌 시 참(true)을 사용할 것이면 true로 놔둡니다.
이제 플레이어 컨트롤러 스크립트를 열어서 스크립팅을 합니다.
public class PlayerMovement : MonoBehaviour { Animator animator; void Start() { animator = GameObject.FindGameObjectWithTag("Player").GetComponent<Animator>(); } private void OnTriggerEnter2D(Collider2D collision) { if (collision.CompareTag("Wall")) { animator.SetBool("isCollision", true); } } } |
기존의 컨트롤러 스트립트에 이 부분을 추가하면 됩니다. 다만 Animator를 담은 변수의 지정에는 다른 방법도 있습니다. 변수를 public으로 선언해서 직접 지정해주는 방법과 이 스크립트처럼 animator변수에 지정을 해주는 방법인데 당연히 지정한 게임 오브젝트에는 Animator 컴포넌트가 있어야 합니다.
OnTriggerEnter2D는 유니티에 있는 함수로써 2D 강체(rigidbody2D)와 2D 콜라이더(collider2D)를 사용한 오브젝트 간에 충돌 시 태그를 비교하여 이벤트를 처리하는 함수입니다. 여기서는 Wall이라는 태그가 있는 게임 오브젝트 충돌 시 충돌 애니메이션을 플레이 하겠다는 뜻입니다.
아직 물체 벽 오브젝트를 만들지 않았기 때문에 아무 2D오브젝트(조건 rigidbody2D와 collider2D 컴포넌트 있어야 함)를 만들고 태그를 Wall 붙여서 테스트 해 볼 수 있습니다.
다음에는 벽, 바닥 등 캐릭터가 움직이는 공간에 대해서 포스팅하겠습니다.