본문 바로가기

코딩 이야기/유니티

유니티 2D RPG 강좌 #3 - 플레이어 애니메이션 적용


저번 강좌에서 플레이어가 움직이도록 코딩을 해 보았습니다. 하지만 아직 뭔가가 조금 아쉽죠? 플레이어가 움직이긴 하지만 애니메이션이 없으니 움직인다기 보다는 그냥 옆으로 슬라이딩(?)하는 느낌입니다. 그래서 이번 강좌에서는 플레이어가 걷는듯한, 움직이는 느낌을 받을 수 있도록 애니메이션을 설정해 보도록 하겠습니다. 





유니티 2D RPG 강좌 #2 - 플레이어가 움직이도록 해보자!

유니티 2D RPG 강좌 #1 - 스프라이트 설정하기

게임 만들기를 위한 유니티 3D 를 설치해 보자!






첫번째 강좌에서 플레이어 스프라이트를 16개로 나눴던걸 기억하시나요? 이 조각들을 이용해서 애니메이션을 만들겁니다. 중간 중간에 더 많은 그림들이 들어가면 더욱 자연스러운 애니메이션이 나오겠지만 시간도 오래걸릴 뿐더러 전문가가 아니기 때문에 그냥 간단하게 3개의 그림 가지고 상하좌우 애니메이션을 만들도록 할게요. 



상단 메뉴에서 "Window > Animation"으로 들어가 줍시다. 



그러면 위 사진처럼 애니메이션 패널이 생길겁니다. Hierarchy 패널에 있는 "Character_0" 오브젝트를 클릭하면 "Create" 버튼이 생기는데요, 클릭해 줍시다. 



애니메이션 이름과 저장할 위치를 정하라고 하네요. 먼저 아래쪽으로 움직이는 애니메이션을 만들어 봅시다. 이름은 "Player_Move_Down" 그리고 위치는 "Animations" 폴더를 만들어서 여기에 저장해 줍시다.



플레이어 스프라이트를 보시면 각 방향(상하좌우)마다 4개의 그림들이 있습니다. 이중 첫 3개가 움직일 때 사용할 애니메이션 그림입니다. 그럼 이 그림들로 어떻게 해야 애니메이션이 되는걸까요? 애니메이션의 원리는 다들 아시죠? 스틸 이미지들이 빠르게 넘어가면서 움직이는 것 처럼 보이는 것인데요, 유니티에서도 마찬가지입니다. 프래임들이 빠르게 넘어가면서 애니메이션이 생성되는거죠. 오른쪽 애니메이션 패널에 줄들이 있는데요, 이 줄 하나 하나가 프래임 1개를 뜻합니다. 스프라이트에서 Character_0 > Character_1 > Character_0 > Character_2 순서대로 각 프래임(줄)마다 하나씩 드래그 해줍시다. 



지금 이대로 애니메이션을 실행해보면 너무 빠르다는걸 느낄 수 있습니다. 1초에 60프래임이 넘어가도록 설정해 뒀는데 우리는 그림이 4개밖에 없어서 그런데요, 프레임을 조금 낮추면 애니메이션 속도가 줄어듭니다. 반대로 프래임 수를 늘리면 속도가 더 빨라지죠. "Samples"를 10으로 낮춰봅시다. 






나머지 애니메이션들도 만들어야겠죠? "Preview > Create New Clip"을 클릭해 줍시다(사진에 실수가 있네요)



이번에는 위로 움직일때의 애니메이션을 만들어 봅시다. 아까와 같이 위치는 Animation 폴더에, 이름은 Player_Move_Up으로 설정해 주세요. 



위를 보는 애니메이션은 "Character_4 > Character_5 > Character_4 > Character_6" 순서대로 각 프래임마다 하나씩 배치하시면 됩니다. 이번에도 Samples를 10으로 줄여서 너무 빠르지 않도록 설정해 주세요. 이런 식으로 좌우 애니메이션도 만들어 줍시다



마지막으로 플레이어가 가만히 있을 때의 애니메이션이 필요합니다. 이름은 Player_Idle.



저는 플레이어가 가만히 있을 때 사용할 그림을 따로 그리지 않아서 그냥 Character_0만 사용하도록 하겠습니다. 



애니메이션을 모두 만들었으면 Animation 폴더에 위 사진처럼 5개의 애니메이션들이 있을겁니다. 



.




애니메이션을 만들었으니 언제 애니메이션을 실행할지를 설정해야겠죠. 유니티에는 Animator이라는 애니메이션 관리를 도와주는 기능이 있습니다. "Window > Animator"로 들어가 줍시다. 



플레이어 오브젝트를 선택하면 위 사진처럼 아까 만든 애니메이션들이 보일겁니다. Player_Move_Down 애니메이션이 주황색으로 되어있죠? 우리가 Player_Move_Down 애니메이션을 제일 처음 만들어서 이 애니메이션이 기본으로 설정되어있는데요, 그러면 게임을 실행했을때 아래로 움직이는 애니메이션이 바로 실행됩니다. 하지만 그러면 안되죠. 가만히 있을 때의 플레이어 애니메이션, Player_Idle을 기본으로 설정해 줍시다. Player_Idle을 우클릭한 뒤 "Set as Layer Default State"를 클릭해 줍시다. 그러면 Player_Idle이 주황색으로 바뀌면서 기본 애니메이션이 됩니다



이제 언제 어떤 애니메이션이 실행될지를 설정해야하는데요, Horizontal과 Vertical 설정을 기억하시나요? 저번 강좌에서 설명했듯이 오른쪽과 위쪽은 +1, 왼쪽과 아래쪽은 -1의 값을 가집니다. 이걸 잘 활용하면 Animator에 있는 기능을 사용해서 쉽게 설정을 할 수 있습니다. "Parameters" 탭으로 들어가신 후 "+ > Float"를 클릭해 줍시다. 좀 있다 설명해 드릴거지만 이 파라미터들을 사용하면 다른 애니메이션으로 넘어갈 조건을 설정할 수 있습니다. 



두개의 파라미터들을 만들어 주는데요, 하나는 "MoveX", 다른 하나는 "MoveY"라고 이름을 지어줍시다. 



그럼 이제 애니메이션들을 서로 연결시켜줄 트랜지션(Transition)을 만들어 줍시다. Player_Idle을 우클릭한 뒤 "Make Transition"을 클릭해 주세요. 



그러면 화살표가 생기는데요, Player_Move_Up을 클릭해서 트랜지션을 생성해 줍시다. 






화살표를 클릭하면 오른쪽 Inspector 패널에서 트랜지션 설정을 할 수 있습니다. 우리는 아래 Conditions를 사용할건데요, "+" 버튼을 클릭한 위 사진처럼 설정해 주세요. 조금 있다가 MoveY가 Vertical, MoveX가 Horizontal 설정과 같게 설정해 줄것이기 때문에 위로 올라갈때는 Vectical이 +1, 즉 MoveY가 0보다 클 때 Player_Move_Up 애니메이션으로 넘어가도록 설정해 주는겁니다. 



나머지 트랜지션도 위 사진을 참고하면서 설정해 줍시다. 상하 움직임은 MoveY, 좌우 움직임은 MoveX를 맞춰 주시면 됩니다. 


트랜지션을 다 설정했으면 코딩을 조금 해야합니다. MoveX와 MoveY가 Horizontal과 Vertical 값과 같도록 설정해야 되는데요, PlayerController.cs 스크립트를 열어준 후 아래 코드를 추가해 줍시다. 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour {

        public float moveSpeed; // 플레이어 속도

        private Animator anim; // Animator를 불러오기 위한 변수

	// Use this for initialization
	void Start () {
        
        // anim 변수 선언
        anim = GetComponent<animator>();
	}
	
	// Update is called once per frame
        void Update () {

        // 왼쪽, 오른쪽으로 움직이기
        if (Input.GetAxisRaw("Horizontal") > 0f || Input.GetAxisRaw("Horizontal") < 0f) { 
            transform.Translate(new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime, 0f, 0f));
        }

        // 위, 아래로 움직이기
        if (Input.GetAxisRaw("Vertical") > 0f || Input.GetAxisRaw("Vertical") < 0f) { 
            transform.Translate(new Vector3(0f, Input.GetAxisRaw("Vertical") * moveSpeed * Time.deltaTime, 0f));
        }

        // 에니메이션 MoveX, MoveY 
        anim.SetFloat("MoveX", Input.GetAxisRaw("Horizontal"));
        anim.SetFloat("MoveY", Input.GetAxisRaw("Vertical"));
	}
}

어제는 public 변수를 만들었는데, 오늘은 private 변수를 만들었습니다. public과 달리 private 변수는 다른 스크립트에서 이 변수에 접근할 수 없는데요, Animator 변수는 다른 스크립트에서 사용될 필요가 없기 때문에 private 설정을 해두는 겁니다. 굳이 private라고 적지 않고 그냥 "Animator anim;"이라고만 적어도 됩니다. 


Start 함수는 게임이 시작되는 즉시 딱 한번만 실행되는데요, 그렇기 때문에 대부분 변수 선언을 할 때 사용됩니다. 우리가 아까 만든 anim 변수에는 아직 어떤 Animator를 사용할지 선언을 안해줬는데요, GetComponent 코드를 통해서 플레이어 오브젝트에 적용되어있는 Animator를 선언시켜 줄 수 있습니다.


마지막으로 SetFloat 코드를 통해서 아까 만든 MoveX와 MoveY가 Horizontal과 Vertical 값과 같도록 해 줍시다. SetFloat(Flaot 파라미터 이름, 값) 형식으로 되어있으니 참고하세요. 



이제 게임을 플레이 해봅시다. 방향키를 누르면 플레이어가 그 방향을 바라보면서 애니메이션이 실행되는데요, 방향키를 때도 여전히 애니메이션이 실행되는걸 볼 수 있습니다. 



Idle 상태에서 움직이는 애니메이션으로 넘어가는 트랜지션은 있지만 움직이는 애니메이션에서 Idle 상태로 넘어오는 트랜지션이 없어서 계속 애니메이션이 실행되고 있는겁니다. 그럼 움직이는 애니메이션에서 Idle 상태로 넘어오는 트랜지션을 만들어 줘야겟죠. 아까와 같은 방법으로 Player_Move_Right 에서 Player_Idle로 넘어오는 트랜지션을 만든 뒤 MoveX가 0.5보다 작을 때로 설정해 줍시다. 오른쪽 방향키를 눌렀을 때는 Horizontal 값이 +1이 되었다가 방향키를 때면 0이 되는데요, 그렇기 때문에 0.5보다 작을 때로 설정을 해서 0이 되었을 때를 정의하는겁니다. 



같은 방법으로 나머지 애니메이션들도 트랜지션을 만들고 설정을 해 줍시다. 



지금 게임을 실행하면 방향키를 눌렀을 때 애니메이션이 실행되고 방향키를 때면 Idle 상태로 돌아갑니다. 하지만 조금씩 딜레이도 있고 어색한데요, 지금 설정은 애니메이션이 무조건 끝나고 다음 애니메이션으로 넘어가도록 설정되어 있어서 그럽니다. 트랜지션 설정에 들어가서 "Has Exit Time"과 "Fixed Duration"을 언체크 한 뒤 "Transition Duration"을 0으로 설정해 줍시다. 8개의 트랜지션 모두 설정해 주시면 우리가 원하는데로 애니메이션이 실행될겁니다. 


오늘은 강좌가 좀 길었네요. 다음 강좌에서는 애니메이션을 조금 더 다듬어 보도록 하겠습니다.





유니티 2D RPG 강좌 #2 - 플레이어가 움직이도록 해보자!

유니티 2D RPG 강좌 #1 - 스프라이트 설정하기

게임 만들기를 위한 유니티 3D 를 설치해 보자!