[인벤게임컨퍼런스(IGC) 발표자 소개] 이득우 교수는 전 유니티 테크놀로지스 한국지사 이사를 역임했으며, 현재 BIC 조직위원회 사무국장, 청강문화산업대학교 교수로 재직 중이다. 이번 강연에서는 언리얼 엔진의 생산성을 높이기 위한 에디터 확장에 대해 강연할 예정이다.
많은 게이머가 알다시피 현업에서 대작 게임은 언리얼로 만드는 경우가 많다. 하지만 현업과 학생 사이에서는 정보량의 차이가 크다. 단순히 현업이니까 많이 알고 있다는 게 아니라 학생들이 참고할 자료가 너무 적기 때문이다.
그렇다면 현업 종사자들과 학생들의 가장 큰 차이는 뭘까? 그리고 그 격차를 극복하기 위해선 뭘 알아야 할까? 청강문화산업대학교 이득우 교수는 이날(18일) 연단에 올라 그 의문에 대한 답을 공유했다.
■ 강연주제: 언리얼 에디터 확장을 위해 알아야 할 것들
현업 종사자와 학생의 격차를 가장 실감할 때는 바로 다음과 같은 상황이 발생할 때다.
1. 예전에는 잘 됐는데, 버전업하니 동작하지 않는다.
2. 매뉴얼대로 기능을 구현했는데 안 된다.
3. 유튜브에선 잘만 쓰던데 내가 하니 안 되더라.
현업 종사자들이라면 어떻게 할까? 아마 엔진의 소스코드를 보고 문제의 원인을 찾아서 고칠 거다. 언리얼 엔진은 소스코드가 공개됐기 때문이다. 여기서 현업 종사자와 학생의 격차를 알 수 있다. 스스로 문제를 해결할 수 있느냐 없느냐 하는 부분이다. 즉, 학생들이 현업에 뛰어들기 위해서는 스스로 문제를 파악하고 해결하는 능력을 기를 필요가 있다.
하지만 갑자기 그 능력이 길러질 리가 만무하다. 학생들의 경우 블루프린트로 콘텐츠를 만들고 이후 유튜브로 유사한 튜토리얼 찾아서 따라 하다가 안 되면 질문하는 식으로 접근한다. 그런데 현업에선 다르다. 앞서 C++을 사용해 최적화된 콘텐츠를 만들고 문제가 생기면 앞서 설명한 것처럼 소스코드를 분석해 원인을 파악한다.
이처럼 현업 종사자와 학생들의 능력은 극단적으로 나뉘어 있다. 그렇다면 이걸 어떻게 뛰어넘어야 할까?
⊙ 언리얼 엔진의 구성 이해하기
이 격차를 뛰어넘기 위해선 언리얼 엔진이 어떻게 구성됐는지 이해할 필요가 있다. 보통 언리얼 엔진을 쓴다는 건 에디터 사용법을 배운다고 생각하기 마련인데 그걸로 끝내선 안 된다. 진짜 프로그래머가 되기 위해선 콘텐츠를 개발하는 것과는 별개로 엔진의 내부 구조를 이해하고 활용해야 한다. 비유하자면 나무가 아닌 숲을 보고 전체적으로 어떻게 발전할지 계획을 세워야 한다는 거다.
그러기 위해선 언리얼 엔진의 모듈 시스템을 이해해야 한다. 모듈이란 언리얼 엔진을 구성하는 요소들로 이 모듈들을 이해해야만 언리얼 엔진 자체를 이해한다고 할 수 있다.
언리얼 엔진의 모듈은 용도에 따라 크게 3가지로 구분된다. 개발과 게임에 모두 사용되는 필수 모듈인 런타임, 개발에 필요한 모듈이지만 게임 릴리즈에서는 제외되는 개발자 모듈, 에디터 제작에 특화된 에디터 모듈이다.
이걸 기능적으로 본다면 런타임 모듈이 가장 아래에 위치하고 그 위에 개발자 모듈이, 최상단에는 에디터 모듈이 위치한다. 이처럼 언리얼 엔진에는 굉장히 많은 수의 모듈이 있고 잘 정리돼 있다.
런타임 모듈에는 기반 시스템이 정의돼있는 코어를 기반으로 관리받는 모듈인 코어U오브젝트와 엔진이 올라간다. 만약 개발자가 게임 개발에 필요한 새로운 모듈을 넣는다면 이 런타임 모듈에 포함된다. 여기서 중요한 게 바로 이 관리받는 모듈이다. 게임을, 콘텐츠를 개발한다는 건 이 모듈을 이용한다는 것과 마찬가지이기 때문이다.
관리받는 모듈이 중요한 이유는 이걸로 게임 플레이 시뮬레이젼 로직을 짜기 때문이다. 이 로직의 비중 자체가 크진 않다. 실제로 게임을 렌더링하고 시뮬레이션하는 수치 연산 모듈이 CPU 코스트의 대부분을 차지한다. 하지만 고작 10%밖에 차지하지 않는 게임 플레이 스뮬레이젼 로직에서 게임이 만들어진다.
그럼 본격적으로 관리받는 모듈에 대해 알아보도록 하자. 일반적으로 언리얼 엔진을 활용해 콘텐츠를 만들 때는 에디터 UI를 사용해 다양한 에셋을 제작, 편집하고 작업한 결과물을 저장한 후 게임에서 이를 로딩해 실시간으로 사용하는 프로세스가 적용된다. 이 프로세스를 모듈로 본다면 에디터에서 런타임 모듈의 객체를 편집해 저장한 후 게임에서 이를 사용하는 식으로 볼 수 있다.
즉, 에디터 모듈을 파악해야 한다는 건데 이를 위해서는 네이티브와 슬레이트 모듈에 대해 이해해야 한다. 그러기 위해선 C++을 제대로 다룰 필요가 있다. 다행스럽게도 언리얼 엔진은 코어 모듈을 통해 그나마 편리하게 C++ 프로그래밍을 지원한다. 코어 모듈은 다양한 플랫폼에 균일한 모델을 제공하는데 여기에 각종 수학 함수부터 자료구조, 직렬화, 델리게이트, 스마트포인터 등도 지원하는 걸 확인할 수 있다.
모듈 다음으로는 코어의 객체를 알아야 한다. 코어는 용도에 따라 네이티브(F), 슬레이트(S), 오브젝트(U), 액터(A) 4개의 클래스로 구분된다. 네이티브는 C++이라고 보면 되고 슬레이트는 UI제작에만 사용하며, 오브젝트와 액터는 콘텐츠 제작에만 사용한다.
우선 알아야 할 건 네이티브다. 네이티브 클래스를 다루기 위해선 언리얼 엔진의 스마트 포인터 시스템과 라이브러리를 알 필요가 있다. 이중 스마트 포인터는 F 클래스에서만 사용 가능한데 굳이 사용하진 않아도 된다. 하지만 일반 포인터가 생성과 소멸을 직접 해야 해서 중간에 에러가 발생할 수 있는 반면, 포인터는 자동으로 소멸하기에 에러를 방지할 수 있다.
⊙ 언리얼 에디터 확장 예제
모듈에 대한 대략적인 것들을 알았으면 이제는 이걸 활용해서 에디터를 확장시킬 때다. 이 과정은 크게 8단계로 구분된다. 추가할 모듈은 에디터 모듈이기에 게임 빌드에는 포함되지 않는, 개발의 편의성을 올리는 모듈이다.
일반적으로 언리얼 에디터는 맨 처음 실행하면 나오는 레벨 에디터, 렌더링을 보여주는 뷰포트, 각종 세부사항이 있는 디테일 뷰 등으로 나뉜다. 이렇게 에디터 모듈에 대해 파악했다면 다음은 메뉴와 툴바를 제작해야 한다.
레벨 에디터에 메뉴를 추가하기 위해선 커맨드와 액션을 이용해야 한다. 커맨드는 명령을 어떻게 정의할지 기획하는 요소이고 액션은 버튼을 눌렀을 때 결과를 보여주는 거다. 이 두 개를 연동한 후 메뉴와 툴바를 삽입해야 한다.
메뉴와 툴바를 추가하기 위해선 우선 삽입 위치를 지정해야 한다. 이 위치는 문자열로 확인할 수 있다. 평소에는 안 보이지만 에디터의 개인설정의 기타 -> Display UIExtension Points 항목을 체크하면 확장 포인트를 볼 수 있다. 이 위치를 보고 메뉴를 삽입하면 된다. 이걸 할 수 있으면 이후 게임 제작에 필요한 명령어를 추가, 확장할 수 있다.
메뉴와 툴바를 만들었으면 다음으론 아이콘을 입히는 UI 작업에 들어가야 한다. UI를 만들기 위해선 우선 스타일 셋에 사용할 아이콘 텍스쳐를 등록하면 이제 이걸로 메뉴와 툴바를 꾸밀 수 있다.
다음으로는 본격적인 에셋 에디터를 생성할 때다. 에셋 에디터란 간단히 말해서 특정 종류의 에셋을 편집할 때 뜨는 전용 에디터를 의미한다. 보통 스태틱 메시 에디터, 스켈레탈 메시 에디터, 머티리얼 에디터, 이펙트 에디터로 구성된다. 이런 에셋 에디터는 에셋의 속성을 편집하는 디테일 창과 에셋을 볼 수 있는 뷰포트 창으로 이뤄져있다.
에셋 에디터는 U 접두사를 가지는데 콘텐츠에 사용되므로 런타임 모듈에 위치한다. 에셋 에디터를 만든 다음에는 기본 레이아웃을 설계해야 한다. 보통 상단 10%는 메뉴로 그 외 나머지 60%를 뷰포트, 나머지를 디테일 뷰로 구분한다.
에셋 에디터를 만들었으면 이제 내용물을 넣을 때다. 내용물을 넣기 위해선 UI를 실제로 만들어서 탭 콘텐츠에 등록하는 작업을 먼저 해야 한다. 단, 언리얼 엔진은 객체를 생성할 때 4개의 객체마다 각각 다른 방법으로 생성해야 한다는 걸 알 필요가 있다. 예를 들어 네이티브는 new로, 슬레이트는 SNew로 생성하는 식이다.
이렇게 객체를 생성했으면 이제 디테일 뷰를 편집할 시간이다. 디테일 뷰를 편집할 때는 새로 만들 필요가 없다. 이미 에디터에 있는 좋은 기능을 가져다 쓰면 끝이다. 프로퍼티 에디터 모듈의 코드를 참조해 API를 생성해 탭에 넣어주기만 하면 된다. 이 방식은 디테일 뷰 외에 다른 UI에도 사용할 수 있다.
슬레이트 클래스는 공유 레퍼런스라는 걸 익혀서 작업을 진행해야 한다. 사실 공유 레퍼런스는 안 써도 되지만 UI 관련 라이브러리가 다 공유 레퍼런스를 반환하게 돼 있는 만큼, 익히는 걸 추천한다.
이렇게 프로퍼티 에디터를 불러서 탭에 집어넣으면 언리얼 엔진이 알아서 분석해서 화면을 띄운다. 코드 몇 줄만으로 에디터를 만들 수 있는 것이다.
이제 뷰포트 위젯을 생성할 차례다. 아마 제일 많이 관심을 갖는 부분이 아닐까 싶다. 렌더링 화면을 보여주는 기능인데 뷰포트를 다루려면 뷰포트 클라이언트, 뷰포트, 프리뷰 씬 프로세스를 요소를 이해할 필요가 있다. 간단히 설명하자면 에디터가 뷰포트 클라이언트에 명령을 내리면 뷰포트 클라이언트는 명령을 인식, 해석해서 이걸 뷰포트로 전달한다. 뷰포트는 렌더링을 위한 씬 컴포넌트를 추가하고 마지막으로 프리뷰 씬에서 렌더링을 수행하는 식이다.
뷰포트를 생성했으면 이제 직접 다룰 때다. 뷰포트가 만들어지면 오버레이 위젯이 제공되는데 여기에 필요한 위젯을 배치해 UI를 그릴 수도 있다. 또한, 각종 씬 컴포넌트를 추가해 다양한 에셋의 시각적 효과도 확인할 수 있다. 본인의 취향대로 뷰포트를 만들 수 있다는 얘기다.
언리얼 에디터 확장에 대한 설명을 끝마치고 이득우 교수는 "언리얼 엔진을 사용하면서 발견한 모든 기능들은 소스 코드에 있어서 내 것으로 만들 수 있다. 이걸 보고 자신만의 에디터를 꾸미는 한편, 소스 코드를 분석하는 능력을 기르길 바란다"고 전하며 강연을 마무리했다.