지금까지 배웠던 기초 프로그래밍을 기반으로, 본격적으로 게임을 만들 툴인 유니티 엔진에 대해 알아보고자 한다.
게임의 초기 개발에는 어셈블리 언어로 제작하거나, 최소한의 용량을 사용하는 게임 개발 방식이 필요했었다.
ex) 어셈블리 언어로 개발된 롤러코스터 타이쿤, 40kb란 용량으로 발매되었던 슈퍼마리오 최초 발매본
하지만 게임 개발을 하는 회사와 데이터가 누적됨과 동시에, 그래픽 / 사운드 등을 다루는 소스 코드가 비슷해지는 경우를 겪게 되었다.
이런 식으로 재사용성이 있는 코드를 모아 '엔진'으로 개발하고, 자사 게임 개발 목적이 아닌, 해당 엔진만의 개발 및 배포를 위한 회사(상용 엔진 개발 회사)가 생겨나기 시작했다.
이것이 현 시점에서 게임 엔진의 시초가 되었다.
프로그래밍에서의 엔진 : 필요한 기능 모듈을 의미한다.
따라서 게임 엔진이란 것은 게임을 개발하는데 범용적으로 많이 사용되는 기능 모듈을 모아놓은 기능 묶음과 도구들을 말한다.
게임 회사에 따라서는 자체 게임 엔진이 있는 경우가 있으며, 상용 게임 엔진으로 게임을 개발하는 경우로 나뉠 수 있다.
상용 게임 엔진의 경우 다양한 종류가 있다 - 유니티, 언리얼 엔진, 크라이, 기타 등등
이에 따라 상용 게임 엔진을 쓰느냐, 자체 게임 엔진을 쓰느냐 선택하는 시대가 오게 되었다.
상용 엔진을 사용하는 이유에 관해서는 다음 세 가지 이유가 있다.
게임 개발사에게 있어서 가장 큰 비용부담이 되는 것은 개발 기간이다. 게임 엔진을 개발하는 기간을 상용 엔진을 대체하는 것으로 개발 기간을 단축하며, 비용 절감 효과를 볼 수 있다.
게임 개발사 입장에서 게임 엔진을 사용하는 비용보다 게임엔진을 사용하지 않았을 때 비용이 더 크다.
게임 엔진을 사용하여 개발을 하는 경우 팀원 모두 같은 기준을 가지고 협업할 수 있다.
자체 게임 엔진을 사용하고 있는 게임개발사 같은 경우 새로운 팀원이 합류한 경우에 기존 기능에 대한 파악을 하기 위한 시간이 필요하게 된다.
반면에 상용 게임 엔진의 경우 해당 기능에 대한 파악을 하기 위한 시간이 단축된다.
프로그래머가 익숙하지 않은 기술을 완성도 있게 만들어내는 것은 어렵다.
만약 게임 엔진 기술을 만드는 데에 능숙한 전문가가 개발한 기능을 이용할 수 있다면, 더욱 높은 퀄리티의 결과물을 낼 수 있다.
위와 같은 이유로 상용 게임 엔진을 사용하는 메리트가 있다.
위에서 상용 게임 엔진을 사용하는 이유에 대해서 서술하였다. 그러면 개발자 입장에서 상용 게임 엔진을 쓰는 게 좋다는 것은 알 수 있을 것이다. 하지만 단순히 상용 게임 엔진을 쓸 줄 안다는 것만으로는 전문적인 개발자가 되기는 어려울 수 있다.
이제는 역으로, 개발자로서 상용 게임 엔진에 대해서 이해도가 필요한 이유에 대해서 서술하고자 한다.
프레임워크는 게임이 동작하는 핵심 로직을 구현하는 것을 말한다.
개발자로서 필요한 역량으로서, 단순히 돌아가는 게임을 만드는 것이 아니라 효율적으로 돌아가는 로직에 대한 이해가 필요하다.
게임은 게임루프, 컴포넌트 구조, 랜더링 파이프라인 등 게임에 필요한 핵심 로직을 기반으로 돌아가며, 이를 기반으로 프로그래밍을 할 필요가 있다.
유니티 또한 게임 엔진으로 핵심로직을 기반으로 하고 있고, 이를 토대로 게임 컨텐츠를 구성해야 한다.
생산성 향상
게임엔진을 기반한 라이브러리의 경우 최적화를 위해 시스템 코드가 포함된 경우가 있으며, 이를 분석하여 사용하기 위해선 게임엔진에 대한 이해도가 필요하다.
기능 변경
보통의 경우 게임엔진의 기능을 메뉴얼에 맞추어 사용하겠지만, 이를 상황에 맞춰 다르게 사용해야 하는 경우가 있다. 응용할 수 있는 기술을 다지기 위해선 게임엔진에 대한 이해도가 필요하다.
유니티를 처음 실행시키면 아래와 같이 화면이 나온다.
각 기능이 무엇인지 확인해보기로 하자.
둘러보기 위한 기능. 핸드 툴을 설정하여 사용하거나 마우스 휠 버튼을 누른 채로 사용 가능.
핸드 툴로만 이동하기 어려울 경우 우클릭 후 WASD/QE를 사용하여서도 이동이 가능하다.(Flythrough 모드)
또한 이동속도를 조정할 경우 우측의 카메라 버튼에서 속도 조절도 가능하다.
게임 오브젝트를 움직이기 위한 기능.
기즈모(화살표 및 박스)를 이용하여 오브젝트의 위치를 조정할 수 있다.
컨트롤을 누른 채로 이동하면 일정한 거리만큼 이동이 가능하다.
물체를 회전시킬 수 있다.
컨트롤을 누른 채로 돌리면 일정한 각도만큼 돌릴 수 있다.
물체의 크기를 조정할 수 있다.
컨트롤을 누른 채로 돌리면 일정한 크기만큼 조정할 수 있다.
주로 2D 게임 제작에서 활용된다.
사각형 형태로 물체의 크기를 조정할 수 있다.
1~5 기능 전부 한 번에 사용하기
오브젝트의 기준점. 프로그래머는 Center 안 쓰고 Pivot 쓴다고 생각하면 됨.
Pivot : 오브젝트의 바닥 기준으로 움직임
Center : 오브젝트의 중심 기준으로 움직임
오브젝트 방향의 기준점.
Local : 오브젝트 중심으로 X, Y, Z가 결정됨
Global : 전체 월드 기준으로 X, Y, Z가 결정됨
맵에 표시된 격자를 표시하거나 표시하지 않는 것.
해당 버튼으로 격자의 크기를 조정할 수 있다.
다양한 조건에 따른 그래픽 옵션으로 게임 상황을 확인할 수 있다.
2D는 2D로, 3D는 3D로 작업할 테지만, 3D 환경에서의 경우 UI 제작시에 2D 모드에서 제작할 수도 있음.
조명이 있는 상태 / 없는 상태로 맵을 확인 가능함
게임 테스트 시에 소리를 끄거나 킬 수 있는 기능
물체 중 보이지 않게 설정한 오브젝트를 한꺼번에 안 보이게 설정하거나, 보이게 설정하는 기능
카메라의 시야각 조절이나, 카메라 이동속도 등 카메라 관련 옵션을 조정
기즈모 관련 옵션을 조정할 수 있는 버튼
게임의 재생 환경을 설정한다. Game의 경우 PC게임 화면과 같은 환경을 출력하고, Simulator의 경우 모바일 환경 출력을 보여준다.
게임의 화면 비율을 조정한다. PC게임의 경우 Full HD 화면으로 보는 것을 권장한다.
게임 재생 시에 해당 실행이 씬 뷰에서도 적용하도록 할 건지 선택하는 부분이다.
Play Focused는 씬 뷰에서도 플레이 시점의 카메라 위치로 이동시키고, Unfocused는 시점을 변경시키지 않는다.
유니티 게임엔진은 해당 객체에 컴포넌트를 붙여서 기능을 구현하는 방식으로 만든다.
이와 같이 오브젝트에 컴포넌트(기능 및 특성)를 붙여서 한 오브젝트에 필요한 기능을 완성하는 방식이다.
스크립트를 생성하면 기본적으로 MonoBehaviour 가 상속되어 있는 상태를 확인할 수 있다.
MonoBehaviour 상속이 가지는 기능은 크게 아래와 같이 생각할 수 있다.
해당 스크립트를 유니티 내 게임 오브젝트의 컴포넌트로 사용할 수 있음.
(MonoBehaviour 가 상속되지 않은 스크립트는 게임 오브젝트의 컴포넌트로 사용할 수 없다.)
유니티 메시지 함수를 기본적으로 사용할 수 있도록 하는 기능 (Start, Update 등)
검색에서 'Unity' 로 검색하면 유니티 메시지 함수를 확인할 수 있다.
직렬화 (Serialization)
데이터 구조 또는 게임오브젝트 상태를 보관하고 관리하는 기법으로, 인스펙터 창에서 오브젝트의 직렬화된 멤버변수 값을 보여준다.
이를 이용하여 소스코드의 수정 없이 유니티 에디터에서 값을 변경할 수 있다.
직렬화가 어떠한 것인지 보여주기 위해 3.1에서 보여준 PlayerController의 스크립트를 사용했다.
스크립트에서 이와 같이 Public으로 변수를 선언하고 인스펙터 창을 살펴보자.
인스펙터 창에서 Public으로 선언된 변수가 드러난 것을 확인할 수 있으며, 이곳에서 수치 조정 및 참조 연결이 가능하다.
참조 연결의 경우 드래그로 참조하거나, 오른쪽 버튼을 눌러 참조할 항목을 찾을 수 있다.
유니티 메시지 함수는 앞으로 게임을 제작할 때 게임 라이프 사이클로서 많이 사용하게 될 기능이다.
유니티 메시지 함수
유니티가 보내는 메시지에 반응하는 함수로, MonoBehaviour 클래스에 메시지와 같은 이름의 함수가 반응한다.
스크립트는 유니티 엔진이 보내는 메시지를 받아 사건 타이밍을 확인하며, 메시지 함수에서 정의된 자신의 행동과 기능을 수행한다.
다음으로 자주 사용하게 되는 유니티 함수에 대한 내용을 정리하고자 한다.