0. 들어가기에 앞서
어제자로 가장 기초가 되는 Unity Learn의 Essential 강의를 끝내고, 바로 Junior Programmer 편도 살펴보기로 했다.
이제는 이런 튜토리얼 강의가 쉽게 느껴지는 수준까지 되었을 진 몰라도, 예상치 못하게 몰랐던 내용이 있을 수도 있고 생각지 못한 팁을 얻을 수도 있다는 예상 때문이었다.
아는 내용은 최대한 빠르게 넘어가고 몰랐거나 어려웠던 부분만 다뤄보고자 한다.
우선 강의의 방식은 Essential과 비슷하긴 하지만, 느꼈던 점은 Essential에 비해서 첨부된 동영상의 길이가 좀 길다는 느낌을 받았다.
차라리 Essential처럼 딱 화면상으로 하는 방법만 알려주면 좋겠는데, 계속 말을 하면서 영상의 길이를 늘리는 방식이 솔직히 말해 조금 별로라는 생각이 들었다.
(실제로 하는 방법에 대해서는 텍스트로 딱 3줄만 적혀 있는데 동영상으론 5분 넘게 설명하는 경우도 있었다.)
그래서 영상을 전부 시청하는 것보다는 그냥 아래에 적혀 있는대로 따라하는 방식으로 진행했다.
Essential 강의를 듣고 와서 그렇게 느꼈는지 모르겠지만, 이 Junior Programmer 강의는 이전 강의를 듣고 온 것을 전제로 두지 않은 것인지 조작법부터 다시 가르치고 있는 것이 보였다.
확실히 강의를 정석적으로 처음부터 듣고 오지 않은 사람도 있을 수도 있기는 한데, 이 부분 때문에 이미 배운 부분은 빨리 넘겨버리는 편이 나아보인다고 생각했다.
첫 번째 단원의 내용은 말 그대로 플레이어를 조작하는 방법에 대해서 다루고 있으며, RigidBody, Collider에 대한 내용을 다루고 있다.
또한 카메라가 플레이어를 쫓는 스크립트를 만들고 트럭을 운전하는 프로젝트를 만들게 된다.
내용에 대해서는 뭔가 특이점이 없었다. 이동 방식으로는 처음으론 transform.Translate으로 이동하는 방법을 가르치고, transform.Rotate로 회전을 주어 이동시켰다.
다만 꽤 인상적이었던 건 이후 챌린지 과제로는 유니티 패키지 파일을 제공해 주고서는 여기에서 버그를 고쳐보라는 식으로 과제를 준다는 점이었다. 실제로 챌린지 과제까지도 별로 어려운 부분은 없었고, 버그를 하나씩 고쳐가는 과정이 공부하는 과정에서 도움이 될 것 같기도 했다.
그리고 이 챌린지 과제 안에 보너스 과제가 또 있다.(과제 안의 과제...)
여기서 파란색 글씨를 타고 들어가면 또 4가지 과제가 있다.
이제 여기서부터가 조금 어렵다 싶은 과제가 있었다.
Easy랑 Medium은 할 만했고 Hard는 조금 코드 작성 과정에서 꼬이긴 했지만 해결했다.
그리고 마지막 Expert가 이때까지 시도해보지 않았던 것이다보니 다소 당황할 수밖에 없었던 부분이다.
먼저, 카메라와 관련된 과제에서 생각보다 고전했던 것은 변수의 변동 때문이었다.
시네머신을 사용하는 방법까지는 가지 않고 카메라 두 대를 만들어서 진행하는 방식으로 했다.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] GameObject cam1;
[SerializeField] GameObject cam2;
[SerializeField] bool isCameraOn = true;
void Update()
{
...
if (Input.GetKeyDown(KeyCode.Space))
{
cam1.SetActive(!isCameraOn);
cam2.SetActive(isCameraOn);
isCameraOn = !isCameraOn;
}
}
}
게임 오브젝트로 두 대의 카메라를 참조시키고, 스페이스바를 누를 때마다 카메라가 번갈아가며 활성화되고 비활성화되는 방식으로 했다. 여기에서 맨 마지막의 isCameraOn을 !isCameraOn으로 전환해주지 않았던 실수 때문에 카메라가 한 번밖에 전환되지 않아 고전했었다.
과제 내용은 요악하자면 다음과 같았다.
로컬 멀티플레이어라고 한다면 제일 먼저 떠오르는 것이 크레이지 아케이드였지만, 이렇게 화면 분할까지 되는 모습을 보면 가장 대표적인 게임 예시는 It Takes Two였다.
물론 It Takes Two는 로컬도 되고 온라인 멀티도 되는 걸로 알고 있기는 하다만, 이런 느낌의 게임을 만드는 데 있어 이와 같은 과제가 도움이 될 거라고 생각했다.
이 과제를 해결하기 위해서는 크게 두 가지 부분을 신경 써 주어야 한다.
이 두 가지 부분을 핵심으로, 해당 과제를 해결하는 방법은 다음과 같다.
먼저 이와 같이 Horizontal Input과 Vertical Input을 각각 1, 2로 나누고, 둘의 조작법을 각각 WASD와 방향키로 수정한다.
그리고 플레이어 조작과 관련된 부분을 아래와 같이 수정했다.
public class PlayerController : MonoBehaviour
{
[SerializeField] float speed;
[SerializeField] float turnSpeed;
[SerializeField] float horizontalInput;
[SerializeField] float forwardInput;
[SerializeField] GameObject cam1;
[SerializeField] GameObject cam2;
[SerializeField] bool isCameraOn = true;
[SerializeField] int num;
void Update()
{
// num에 따라 조작법이 달라짐
horizontalInput = Input.GetAxis($"Horizontal{num}");
forwardInput = Input.GetAxis($"Vertical{num}");
if (Input.GetKeyDown(KeyCode.Space))
{
cam1.SetActive(!isCameraOn);
cam2.SetActive(isCameraOn);
isCameraOn = !isCameraOn;
}
}
private void FixedUpdate()
{
transform.Translate(Vector3.forward * Time.deltaTime * speed * forwardInput);
transform.Rotate(Vector3.up, turnSpeed * horizontalInput * Time.deltaTime);
}
}
이와 같이 코드를 작성한 후 플레이어 1에는 1을, 플레이어 2에는 2를 넣는다.
이와 같이 만들면 우선, 스크립트 하나로 2p 조작은 가능해진다.
Viewpoint Rect에 대한 유니티 공식 문서를 살펴보면 위와 같이 설명되어 있다. 즉 여기에서 위와 같이 세로로 두 개의 화면으로 분할되게 재생하도록 하자면, W를 반으로 나누어서 출력하면 되는 것이다.
이에 따라 아래와 같이 수정하면 된다.
Main Camera를 복사하고, 복사한 Main Camera의 AudioListener를 삭제한다.
첫 번째 메인카메라를 왼쪽 1p 플레이어, 두 번째 메인카메라를 오른쪽 2p 플레이어로 배치한다 했을 때, 아래와 같이 세팅한다.
이와 같이 하면 로컬 멀티플레이어 2분할 화면을 만들 수 있다.
1단원의 마지막에는 개인 프로젝트의 플랜을 짜거나, 혹은 팀 프로젝트를 어떻게 진행해야 하는지에 대한 설명이 있다.
실제로 개인 프로젝트 진행을 위한 탬플릿 같은 것도 제공하고 있어 이에 따라 작성해보는 것도 큰 도움이 될 것 같았다.
프로젝트의 계획은 어떻게 짜야하고, 게임의 제작에서 운영 단계까지 어떻게 해야 하는지 상세하게 다루고 있다.
프로젝트 진행 과정은 어떻게 되어야 하고, 어떤 문서와 어떤 계획과정이 들어가고, 어떤 태도를 가지고 프로젝트에 임해야 하는지를 다루고 있다. 내용이 괜찮은 것이 많아 한 번 정리해보는 것도 좋아 보인다.
Mission 1에서는 정말 자동차 운전만 했었는데, 이제부턴 조금 게임다운 것을 만들 예정이다.
간단하게 똥피하기 혹은 닷지와 유사한 게임을 만들어 보려고 한다.
플레이어 컨트롤, 동물을 Instantiate 하는 방법이나 Random.Range의 사용 및 동물을 소환하는 SpawnManager를 만드는 등.
이미 해 봤던 것이라서 특이사항은 없었다.
다만 조금 인상적이었던 건 Bonus 문제가 생각보다 어려운 과제를 내놨다는 거였다.
동물의 Hunger Bar를 동물 위에 띄우는 방식으로, 나는 이미 써 본 방식이긴 하지만 Canvas를 자식 오브젝트로 두고, World Space 단위로 UI를 띄워 게이지가 차는 방식을 스크립팅해야 하는 방식이었다.
조금 배울 점이 있었다고 한다면, 나는 일일히 동물에 들어가서 캔버스를 만들고 있었는데, 여기서는 캔버스 자체를 프리팹화해서 붙였다는 점이다.
유니티 최신 버전에만 있는 기능이라고 적혀 있는 것이었는데, 이 버튼을 눌러 체인이 걸린 상태처럼 만들고 사용하면, 아래와 같이 비율이 고정된 채로 스케일 조정이 가능하다.