본문 바로가기

코딩 이야기/유니티

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


저번에 플레이어 스프라이트를 설정해봤습니다. 하지만 게임이 되려면 플레이어가 움직일 수 있어야 하겠죠? 이번에는 저번에 설정한 스프라이트를 토대로 플레이어가 움직일 수 있도록 코딩을 해보려 합니다. 아직 스프라이트 설정을 안하신 분들은 저번 강좌를 먼저 따라하시고 오시기 바랍니다. 그럼 시작해 볼까요! 이번에는 코드들이 많기 때문에 잘 따라오시기 바랍니다.





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

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






유니티는 게임 제작에 최적화 된 엔진답게 기본적인 움직임, 공격 등을 쉽게 구현할 수 있도록 도와주는 설정이 있습니다. Input 설정인데요, "Edit > Project Settings > Input"으로 들어가 줍시다. 



"Axes"를 열면 위 사진에서 보이는 것 처럼 여러 설정들이 있습니다. 이중 "Horizontal"이 좌우 움직임 설정이고요, "Vertical"이 상하 움직임 설정입니다. 그 외에도 Fire, Jump 등 여러 설정들이 있지만 지금은 Horizontal과 Vertical 설정만 사용할겁니다. 






좀 더 디테일하게 알아볼까요? Horizontal 설정을 열어봅시다. 이 Horizontal 설정은 기본적으로 게임에서 많이 사용하는 좌우 버튼, 즉 왼쪽, 오른쪽 방향키나 A, D 키를 눌렀는지를 확인합니다. 설정에서는 "Negative Button", "Positive Button"으로 적혀있는데요, 이름에서 예상할 수 있듯이 왼쪽으로 움직일때는 -1, 오른쪽으로 움직일때는 +1이 됩니다. Vertical 설정도 마찬가지인데요, 아래로 움직일때는 -1, 위로 움직일때는 +1의 값을 가지게 됩니다. 조금 있다 코딩을 할 때 조금 더 자세하게 설명해 드리도록 하겠습니다. 



그럼 바로 코딩을 시작해보죠. 코드를 보관하기 위한 "Scripts"라는 이름의 폴더를 하나 만들어주신 후 "우클릭 > Create > C# Script"를 클릭해서 C# 스크립트를 만들어 줍시다. C# 스크립트 이름은 "PlayerController"으로 설정해 주세요. 여기서 주의할 점은 스크립트 이름에 스페이스가 있으면 안됩니다. 스크립트를 만들었다면 두번 클릭하시면 Visual Studio가 열리면서 코딩을 할 수 있습니다. 


코드를 처음 만들면 아래 코드처럼 되어있을겁니다. (아쉽지만 이 강좌에서는 유니티에 대한 기본적인 지식은 갖췄다는 가정 하에 기본적인 것들은 설명하지 않겠습니다. 모든걸 다 설명하다보면 너무 힘들어지거든요 ㅋㅋ)

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

public class PlayerController : MonoBehaviour { 

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
        void Update () {

        }
}



.



플레이어가 움직이려면 속도가 있어야겠죠. 속도를 담당할 변수를 하나 만들어 줍시다. 

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

public class PlayerController : MonoBehaviour {

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

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
        void Update () {

	}
}

C#에는 여러가지 종류의 변수들이 있는데요, float 변수는 소숫점 값을 가질 수 있습니다. 보통 속도같은 정밀하게 조절해야 하는 변수들은 float 변수를 사용할 때가 많습니다. 또 나중에 설명할거지만 속도는 나중에 다른 float 변수와 곱해줘야 하기 때문에 대부분 속도는 float를 사용하죠. moveSpeed 변수를 보면 앞에 public이라고 적혀있는데요, public 변수들은 다른 스크립트에서도 이 변수에 접근이 가능하게 해 줍니다. 유니티 엔진에서는 한가지 더 특별한 기능이 있는데요, 변수를 public하게 만들면 Inspecter 패널에서 직접 변수 값을 수정할 수 있습니다. 한번 해 볼까요? 



유니티로 돌아와서 PlayerController.cs 스크립트를 캐릭터 오브젝트로 드래그 해 줍시다. 그러면 오른쪽 Inspector 패널에 Player Controller 스크립트가 적용된걸 볼 수 있는데요, 자세히 보면 "Move Speed"라는 부분이 있을겁니다. 우리는 아직 스크립트에서 아무런 값을 입력해 주지 않았기 때문에 0으로 되어있을건데요, 5로 바꿔봅시다. 


이런 식으로 유니티에서는 public 변수들을 코드를 통해서가 아니라 Inspector 패널에서 직접적으로 수정할 수 있도록 시스템을 만들어 뒀습니다. 게임을 실행해서 테스트 하면서도 값을 바꿀 수 있기 때문에 여러모로 유용한 기능입니다.


그럼 이제 마저 코딩을 해 봅시다.

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

public class PlayerController : MonoBehaviour {

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

	// Use this for initialization
	void Start () {
		
	}
	
	// Update is called once per frame
        void Update () {
        // 왼쪽, 오른쪽으로 움직이기
        if (Input.GetAxisRaw("Horizontal") > 0 || Input.GetAxisRaw("Horizontal") < 0) { 
            transform.Translate(new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime, 0f, 0f));
        }

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

여기서 아까 소개했던 Input 설정이 사용됩니다. Input.GetAxisRaw 코드를 통해서 Horizontal, 혹은 Vertical 설정에 입력되어있는 버튼, 즉 상하좌우 혹은 wsad 키가 눌러졌는지를 확인합니다. 아까 왼쪽과 아래쪽은 -1, 오른쪽과 위쪽은 +1의 값을 갖는다고 했었는데, 기억 나시나요? 플레이어가 왼쪽 방향키를 눌렀다고 가정해 봅시다. 그러면 Horizontal의 값이 -1, 즉 Input.GetAxisRaw("Horizontal") 이 -1이 되겟죠. if 문에서 Horizontal 혹은 Vertical의 값이 0보다 큰지(+1) 아니면 0보다 작은지 (-1) 확인하는 겁니다. 


유니티에서 사용되는 모든 오브젝트들은 각자의 위치 "transform"이 있습니다. 이 transform의 위치를 바꾸는것이 바로 플레이어를 움직이도록 하는건데요, 유니티는 기본적으로 3D 게임에 최적화된 엔진이기 때문에 모든 transform들은 x, y, 그리고 z 축이 있습니다. Vector3 코드는 이 xyz 축을 다루는 코드인데요, 이걸 사용해서 쉽게 플레이어가 움직일수 있도록 할 수 있습니다. 좌우로 움직이는 경우에는 x축에서 이동을 해야하고, 상하로 움직이는 경우는 y축에서 움직여야 하죠. 우리는 지금 2D 게임을 만들고 있기 때문에 앞뒤로 움직이는 z축은 사용할 필요가 없습니다. 





그러면 기본적인 것들을 알았으니 다시 코드를 살펴봅시다. 

transform.Translate(new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime, 0f, 0f));

transform.Translate는 아까 얘기한것처럼 오브젝트의 위치를 바꿀 수 있도록 해주는 코드입니다. 중요한건 얼마나 움직이느냐겠죠. 여기서 Vector3가 사용됩니다. Vector3 코드는 "Vector3(x값, y값, z값)" 형태로 되어있는데요, 좌우로 움직이기 위해서는 x값을 바꾸고 y와 z는 바뀌지 않도록 0으로 나둬야 합니다. 상하로 움직일때는 x와 z가 0, 그리고 y값이 바껴야겠죠


그럼 저 코드가 어떻게 플레이어를 움직일수 있도록 하는걸까요? Input.GetAxisRaw("Horizontal")이 다시 등장했네요. 왼쪽 키를 눌렀을때는 -1, 오른쪽 키를 눌렀을때는 +1의 값이 된다고 했죠. 그럼 이 값을 moveSpeed 변수로 곱하면 어떻게 될까요? 감이 오시나요? -1 곱하기 5는 -5기 때문에 왼쪽 방향키를 눌렀을때는 왼쪽으로 5씩, 오른쪽 방향키를 눌렀을때는 오른쪽으로 5씩 이동하게 됩니다. 


마지막에 있는 Time.deltaTime에 대해서도 설명해 드려야겠죠. 지금 이 코드가 속해있는 함수는 Update 함수인데요, Update 함수는 매 프레임마다 한번씩 실행됩니다. 예를 들어 1초에 20프레임이 있다고 가정해 봅시다. 그렇다면 1초에 이 Update 함수가 20번 실행되는건데요, 오른쪽 방향키를 누르면 5씩 20번, 즉 1초에 100만큼을 움직이게 됩니다. 우리는 1초에 5를 움직이길 바라는데 1초에 100을 움직이는건 바람직하지 않은 결과죠. 그럼 프레임에 맞춰서 변수 값을 정하면 되는거 아닌가요? 프레임은 고정되어있는 값이 아니라 상황에 따라서 매번 바뀌게 됩니다. 그렇기 때문에 프레임에 맞춰서 속도를 조절할 수 있는 Time.deltaTime 을 곱해줘야 합니다. Time.deltaTime은 "1초 / Frame Rate" 값으로, 1초에 20프레임이 있다면 Time.deltaTime의 값은 0.05가 되겠죠. +1 * 5 * 0.05는 0.25지만 이게 20번 실행된다면 5가 됩니다. 즉, 우리가 원하는 속도로 조절이 된다는 뜻이죠. 이해가 가시나요?



코드를 다 적으셨다면 저장하고 가운데 상단에 있는 플레이 버튼을 클릭해 줍시다. 그러면 Game 패널에서 테스트할 수 있는데요, 방향키를 누르면 플레이어가 움직이는걸 보실 수 있습니다. Inspector 패널에 있는 Move Speed 값을 변경하시면 캐릭터가 더 빠르게, 혹은 더 느리게 움직이는 것도 확인해 보실수 있으니 한번 해보세요! 


게임 개발 강좌를 동영상이 아닌 포스트로 작성하다보니 설명하기가 너무 힘드네요. 동영상을 만들면 더 쉽게 설명할 수 있는것들도 글로 적기에는 너무 한정적인 것들이 너무 많은것 같습니다. 그래도 나머지 강좌들도 최선을 다해서 만들어 보겠습니다! 다음 강좌에서는 플레이어 애니메이션을 설정해 보도록 하겠습니다. 





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

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