Udemy에서 게임 개발 강의를 듣고, 게임 개발을 시작한지는 벌써 2주일이 지났지만, 역시 기록으로 남기는게 최고라는 생각이 들어서 velog에 남기기로 했다.
혹시 Tank Hero라는 게임을 알고 있는가?
https://namu.wiki/w/Tank%20Hero
이러한 게임인데, 아주 간단하다. 모바일 기준으로, 왼쪽의 조이스틱을 움직이면서 화면을 터치하면 그쪽으로 포탄이 날아가고, 이것으로 적을 모두 없애면 스테이지 클리어이다. 어렸을 때 재밌게 했던 게임이기도 하고, 2D로 구현하기 쉽다고 생각해서 이 게임을 학습 차원으로 만들어보기로 했다.
유니티 일지를 적기로 했으니, 내가 배운 내용도 같이 적어놓도록 하겠다.
유니티에도 언리얼과 같이 스크립트가 있다. 오브젝트에 스크립트를 넣어 특정한 기능을 가능하게 하고, 이러한 기능들이 모여 게임을 만드는 것이라고 생각하는게 맞을 것이다.
처음 스크립트를 만들면 이러한 내용이 스크립트들에 적혀있다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class [스크립트 이름] : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
유니티는 C#을 사용하기 때문에, 이참에 C#도 간단하게 배울 수 있는 기회가 되어서 좋았다.
우선 1~3번째 줄에 나오는 using은 모두 Java에서의 import, C에서의 include와 같은 역할을 한다고 보면 된다.
C#은 클래스와, 클래스 안의 메서드로 구성되어 있다. 구조 자체는 Java와 비슷하지만, 언어는 C와 비슷해서 둘 다 해본 본인에게는 크게 난이도가 있다고 느껴지지는 않았다. 위 코드도 마찬가지로, 자신이 정한 이름의 클래스와 Start(), Update()라는 메서드로 구성되어있는 것을 확인할 수 있다.
Start() 메서드는 게임을 실행하자마자 바로 실행된다. 즉, 게임을 실행하자마자 실행되어야하는 명령문들은 Start() 안에 적어놓으면 된다.
Update() 메서드는 게임을 실행한 후, 매 프레임마다 실행된다. 즉, 프레임마다 바뀌어야하는 명령어들을 Update() 안에 적어놓으면 된다.
기본적으로 제공되는 메서드는 위의 2개고, 우리가 원한다면 다른 메서드를 추가하여 사용하면 된다.
그럼 Tank Hero 2D를 만들기 위해 필요한 기능들을 하나씩 알아보겠다.
- 탱크는 전후좌우 이동해야한다.
- 탱크에서 포탄이 마우스 방향으로 발사되어야 한다.
- 포탄은 벽에 부딪히면 사라지고, 사라지는 것에 맞춰서 효과가 구현되어야 한다.
- 적은 특정 범위 안에 플레이어가 들어오면, 그것에 맞춰서 사격해야 한다.
- 적을 맞추면 적이 파괴되고, 모든 적이 파괴되면 승리한다.
우선 탱크의 이동이다. 탱크의 이동은 Update 메서드 안에서 transform.Rotate와, transform.Translate를 이용하여 이동과 회전을 모두 구현했다.
[SerializeField] float moveSpeed = 1f;
[SerializeField] float steerSpeed = 1f;
void Update()
{
steerAmount = Input.GetAxis("Horizontal") * steerSpeed * Time.deltaTime;
moveAmount = Input.GetAxis("Vertical") * moveSpeed * Time.deltaTime;
transform.Rotate(0, 0, -1 * steerAmount);
transform.Translate(0, moveAmount, 0);
}
변수 steerAmount는 변수의 이름 그대로, 회전량이다. 또 다른 변수 moveAmount도 변수 이름 그대로, 운동량이다. GetAxis는 유니티의 함수로서, Horizontal과 Vertical에 할당된 키의 입력을 받는다면 -1F ~ 1F의 실수를 출력한다.
transform의 Rotate와 Translate에 접근해, 위에서 만든 변수들을 이용해 위치와 회전량을 바꾼다.
변수 선언은 Update() 메서드 밖에서 해주고, 앞에 SerializeField를 붙인다. 이는 하드코딩을 방지하면서, 외부에서 변수를 바꿀 수 있도록 하기 위해서이다. 하드코딩은 변수를 사용해서 코딩하지 않고, 상수를 사용해서 코딩하는 것을 의미한다. SerializeField를 변수 앞에 사용하면, 변수를 사용함과 동시에 초기값을 마음대로 바꾸면서 원하는 회전량, 운동량을 찾을 수 있다.
위 그림과 같이, VSCode나 Visual Studio를 열지 않고서도 밖에서 변수 초기값을 설정할 수 있는 것을 알 수 있다.
내가 움직이고 싶은 탱크를 하나 만들고, 이 오브젝트에 Collider와 Rigidbody를 적용시켰다.
Collider(콜라이더)는, 내가 특정 오브젝트를 충돌했을때 무언가를 처리하고 싶을 때 사용하는 것이고, Rigidbody는 적용하는 순간부터 오브젝트는 물리엔진의 효과를 받게 된다. 벽에 부딪혔을 때 밖에 나가지 않게 하기 위함이다.
적용시킬 때 주의할 점은, Collider와 Rigidbody 모두 2D와 2D가 아닌 것이 있다. 본인은 현재 2D로서 게임을 제작하고 있기 때문에 모두 2D로 적용했다.
탱크가 만들어졌다면 여기에 아까 제작한 스크립트를 적용한다.
이미 위 기능에서 3번까지는 구현이 되어있으나, 이번 글은 여기서 줄이도록 하겠다.