2018년 1월 1일

이미지를 넘어서: 비주얼 디자인을 경험해보다

저자: Sam Pattuzzi

 

멀티플레이어 게임을 만들고 싶으십니까? 멀티플레이어 게임은 가장 만들기 힘든 게임 유형 중 하나입니다. 하지만 만약 여러분이 멀티플레이어 게임의 팬이시라면, 전세계의 플레이어들과 함께 플레이하는 것이 얼마나 어려운 일인지 아실 것입니다.

언리얼 엔진은 바로 이런 멀티플레이어 게임을 바로 제작할 수 있도록 환상적인 지원을 제공하는 위력적인 게임 엔진입니다. 저희는 여러분들이 멀티플레이어 게임 제작이란 분야를 혼자 개척하고 스스로 첫 걸음을 뗄 수 있도록 돕기 위해 이번 ‘시작하기’ 블로그 가이드 포스트를 작성했습니다.

이 포스트는 U데미(Udemy) 코스에서 상세히 다루는 주제들에 대해 전반적인 설명을 제공합니다. U데미 코스에서는 23시간 분량의 비디오와 실전 예제를 통해 해당 주제를 더욱 상세히 다루게 됩니다(더 자세한 정보를 원하시면 포스트 하단을 참조하시기 바랍니다).

올바른 도구의 사용

멀티플레이어 게임의 종류는 굉장히 다양하며, 각각 다른 사양을 요구합니다. 언리얼 엔진은 그 중 몇몇의 멀티플레이어 게임 유형에 최적화가 되어 있습니다. 이는 언리얼 엔진이 다른 유형의 게임은 만들 수 없다는 뜻이 아니라, 여러분이 다른 툴도 사용할 줄 알아야 한다는 뜻입니다.

UdemyC++UE_Chart.png

* MMO(대규모 멀티플레이 온라인) 게임의 경우, Improbable.io을 확인해 보시기 바랍니다. 이것은 언리얼 엔진과 연계하여 MMO의 일부 어려운 작업들을 쉽게 만들어 줍니다.

언리얼 엔진은 플레이어간 동기화가 필요한 짧은 세션의 게임을 너무나도 쉽게 만들 수 있습니다. FPS, 배틀 로얄, 레이싱 게임, 격투 게임, 그리고 마인크래프트로부터 영감을 받은 샌드박스 유형의 게임도 이에 해당됩니다! 그러니 그 가능성은 무한하다고 봐도 무방합니다.

언리얼 엔진의 멀티플레이어 지원을 다음 3단계, 멀티플레이어 게임의 라이프타임에 따라 분석해 보겠습니다:

  1. 발견
  2. 연결
  3. 동기화

언리얼 엔진으로 얼마나 쉬워질 수 있을까

UdemyC++UE_Inset.jpg언리얼 엔진은 상당히 어려운 멀티플레이 연결 테스트를 엄청나게 쉽게 하도록 만들어 줍니다. FPS 예제를 실행하려면, 플레이 옆 메뉴 버튼을 누르고, 필요한 플레이어 수를 선택한 다음, “새 에디터 창(PIE)”을 눌러주는 게 끝입니다.

어떻게 이것만으로 동작이 될까요? 언리얼 엔진 내부에 있는 수많은 컴포넌트가 모든 어려운 작업들을 해주기 때문입니다.

언리얼 엔진이 여러분 대신 해주는 작업은 다음과 같습니다:

  1. 언리얼 엔진이 을 로드합니다
  2. 맵이 게임모드를 지정합니다
  3. 플레이어컨트롤러가 맵에 참가합니다
  4. 플레이어컨트롤러가 게임모드에게 을 스폰하라고 요청합니다
  5. 폰이 플레이어컨트롤러에 연결이 됩니다

아, 그리고 언리얼 엔진은 네트워크 연결도 맡아서 해 줄 것입니다.

네트워크 연결 구성

언리얼과 함께라면 네트워크 연결도 간단해집니다. 네트워크 연결을 간단하게 시작하는 방법 중 하나는 여러분의 게임을 명령줄로 실행하는 것입니다. 이를 위해서는 윈도우즈(Windows)의 명령 프롬프트나 파워셸, 혹은 맥(Mac)의 터미널(Terminal) 앱을 사용할 수 있습니다.

서버를 실행하하기 위해서는 다음 명령줄을 사용하면 됩니다. 원하는 포트로 대체하고, uproject와 맵에 맞게 경로를 수정해 주시기 바랍니다.

"C:\Program Files\UE_4.17\Engine\Binaries\Win64\UE4Editor.exe" 
"C:\PATH_TO_MY_PROJECT.uproject"
/Game/ThirdPersonCPP/Maps/ThirdPersonExampleMap -server -log -port=8003

서버가 실행되었으면, 이제 여기에 클라이언트도 굉장히 쉽게 연결할 수 있습니다. 이 단계에서 맵을 제공할 필요가 없는 대신 플레이어컨트롤러가 연결할 IP 주소를 제공해야 한다는 점은 명심하시기 바랍니다. IP 주소와 포트는 반드시 올바른 것으로 대체해 주시기 바랍니다.

"C:\Program Files\UE_4.17\Engine\Binaries\Win64\UE4Editor.exe" 
"C:\PATH_TO_MY_PROJECT.uproject" 192.168.1.90:8003 -game -log

맥에서는 위 경로가 살짝 다를 수 있지만, 나머지는 거의 같을 것입니다.

이동(Travelling)

물론 저희들 또한 플레이어들이 위와 같이 복잡한 방식을 따라하길 원치 않으므로, ServerTravel 및 ClientTravel 함수를 사용해 똑같은 작업을 수행하는 UI를 만들도록 합니다.

기본 개념은 한쪽 맵에서 플레이어 컨트롤러의 연결을 끊은 다음, 다른 맵에 다시 연결하는 것입니다. 다만 ServerTravel 함수는 연결된 모든 플레이어컨트롤러(네트워크로 연결된 것들을 포함해서)를 새 맵으로 옮긴다는 차이점이 있습니다. ClientTravel 함수는 플레이어컨트롤러에 존재하는 함수이며 해당 컨트롤러만을 이동시킵니다.

UdemyC++UE_ServerTravel.jpg

실전에서는 ServerTravel 함수를 사용하고 맵 URL의 끝에 “?listen” 스트링을 추가하여 매치를 호스트합니다. 그런 다음 클라이언트가 매치에 합류할 수 있도록 ClientTravel 함수를 사용합니다.

여러분이 공개적으로 접근 가능한 IP 주소를 가지고 있다면 이 방법이 정상적으로 작동하겠지만, 실전에는 NAT에서 막히게 됩니다. 따라서 만약 정상적인 작동을 원하신다면, 포트 포워딩을 구성하거나 하마치(Hamachi) 같은 무료 가상 VPN 솔루션을 사용하셔야 합니다.

하지만 우리는 플레이어들이 IP 주소를 가지고 애를 먹는 상황을 원하지는 않기 때문에, 가상 VPN을 사용하는 경우도 제쳐두도록 하겠습니다. 그러니 여기서는 NAT 순회(NAT traversal)라는 것을 할 수 있는 서비스가 필요합니다.

스팀웍스(Steamworks) SDK

다행히 스팀(Steam)에서는 스팀웍스 SDK의 일부로 NAT 순회를 무료 서비스 제공하고 있습니다. 이 SDK는 온라인 서브 시스템(Online Sub-System, 줄여서 OSS)이라는 플랫폼 독립적인 레이어를 통해 언리얼 엔진과 단단하게 통합이 되어 있습니다.

또한 스팀웍스는 멀티플레이어 게임의 첫 단계: 발견에 대한 솔루션을 제공해주기도 합니다. 스팀웍스는 우리가 게임을 알리고 서버 목록을 표시할 수 있게 해 줍니다. 아래를 보시면 강좌에서 “Donkey”라는 이름의 서버를 표시하도록 제작한 서버 목록 UI를 확인해보실 수 있습니다.

UdemyC++UE_JoinAGame.jpg

권한 보유(Authoritative) 서버 모델

이렇게 발견과 연결이 해결되었다면, 동기화는 어떻게 진행될까요?

서버라는 단어는 들어보셨지만 그게 무엇을 하는지는 정확히 알지 못하실 수도 있습니다. 언리얼 엔진의 게임에서는 서버야말로 모두가 동의하기로 결정하고 아무도 반칙을 하지 못하도록 책임지는 요소로서, 가장 중요합니다. 스포츠 경기의 심판이라고 생각해 보세요!

UdemyC++UE_ClientServer.jpg

위의 다이어그램을 보시면, 서버가 한 클라이언트로부터 액션을 받아(빨간 번개로 표시되어 있습니다), 그 상태를 수정한 다음, 이것을 모든 클라이언트에게 보내는 것을 보실 수 있습니다.

캐릭터 이동 컴포넌트에는 모든 동기화 관련 기능이 이미 작성이 되어 있습니다. 하지만 만약 다른 종류의 움직임을 원할 경우, 어떤 원리로 진행이 되는지 이해를 해야만 합니다.

기본 동기화 툴

액터는 동기화의 기본 유닛입니다. 액터는 클라이언트와 서버 양 쪽에 모두 존재하지만, 서버는 오쏘리티 롤을 갖도록 되어 있습니다. 이것은 그 액터의 서버 버전이 옳은 버전이란 뜻입니다. 클라이언트들은 그 액터가 특정 클라이언트의 통제를 받는 경우를 제외하고 시뮬레이티드 프록시 롤을 가지도록 되어 있습니다. 만약 그 액터가 로컬에서 통제를 받는다면, 액터의 롤은 자율 프록시가 됩니다. 롤을 이렇게 배정한 이유는 액터 코드가 각각 다른 머신에서 다르게 행동하도록 허용하기 위해서입니다.

동기화에는 자율 프록시 클라이언트가 서버에 데이터를 보낼 수 있다는 것이 중요합니다. 그러면 서버는 내부 상태를 업데이트할 수 있고, 이 상태는 마지막으로 클라이언트들에게 다시 내려가야 합니다. 첫번째는 RPC 콜로 끝나고 마지막은 복제 프로퍼티로 끝납니다. 이제 이 둘에 대해서도 다룰 것이 많지만, 여기서 다루지는 않을 것입니다. 대신 강좌에서 각각에 대해 아주 세세하게 다뤄드리도록 하겠습니다.

UdemyC++_UE_Ufunction.jpg

RPC 콜은 로컬(클라이언트)에서 호출한 함수가 서버에서 실행되는 방법입니다. 이를 통해 서버 내 상태를 바꿀 수 있습니다. 여기서 치트는 통하지 않는데, 이런 콜들은 인증 함수를 사용하는 게임의 규칙들로 삼엄한 감시를 받고 있기 때문입니다. 이 부분에 대해서는 강좌에서 더 다루도록 하겠습니다.

UdemyC++UE_UProperty.jpg

프로퍼티 복제는 RPC보다 훨씬 간단합니다. 그저 UPROPERTY에 “Replicated” 특성을 추가해 준 다음 GetLifetimeReplicatedProps 가상 메소드에 상용구만 조금 추가해주면 됩니다. 리플리케이션의 자세한 과정은 이 위키 페이지에서 찾아보실 수 있습니다.

그러면 이것은 자동으로 마법같은 작업을 대신 해 줄 것입니다. 이제 언제든지 프로퍼티에 변화가 생길 경우, 이에 맞춰 클라이언트에 업데이트를 해 줄 것입니다. 하지만 이 과정은 즉시 일어나는 것은 아닙니다(어쨌든 빛도 세계를 도는 데는 시간이 걸리는 법입니다). 따라서 클라이언트는 서버가 업데이트를 해 줄 때까지 기다리는 동안 뭔가 할 일이 필요합니다.

진짜 힘든 작업의 시작...

게이머 입장에서 경험하는 랙은 정말 끔찍한 현상입니다. 게임 프로그래머 입장에서 랙을 해결해야 한다면 악몽이기도 합니다.

UdemyC++UE_Lag.jpg

랙은 여러분과 서버 사이에서 벌어지는 모든 프로세스로 인해 만들어집니다. 라우터는 여러분의 패킷을 복사하여 처리해야 하고, 서버도 자체적으로 계산할 것이 있으며 데이터 전송에 걸리는 시간도 골칫거리입니다. 따라서 실제로 (상황이 나쁠 경우에는) 서버로부터 응답을 받는 데 100ms가 걸릴 수 있습니다.

100ms는 키를 누른 다음 그 반응을 보는 데 있어 도저히 수용할 수 없는 지연 시간입니다. 게임을 플레이할 수 없는 수준으로 만들죠. 이런 이유로 인해 클라이언트가 더욱 부드럽고 랙이 없는 것처럼 보이게 하는 기술들이 많이 있습니다. 이 기술들은 모두 약간의 타협이 필요하기 때문에, 어떤 기술을 사용할지는 여러분이 어떤 게임플레이 경험을 만들고 싶은가에 달려 있습니다.

사실 CharacterMovementComponent는 이런 기술들 중 하나를 구현해서, FPS 예제는 높은 랙에서도 매우 잘 작동합니다. 하지만 자신이 커스텀한 유형의 움직임을 원한다면, 이런 기술들을 스스로 구현할 수 있는 방법을 알아야 할 것입니다.

슬프지만 이런 기술들은 블로그 포스트 하나에서 다룰 수 있는 범위를 벗어나 있으며, 저희 강좌의 마지막 파트에서 훨씬 더 자세하게 다뤄집니다. 그 곳에서는 랙 문제에서 완전히 자유롭게 움직이는 카트 액터 하나를 만들어 볼 것입니다.

심화

이 안내가 도움이 되었길 바랍니다. 여러분의 생각을 코멘트로 남겨주세요.

솔직히 말하자면, 블로그 포스트에서 다룰 수 있는 내용은 제한되어 있습니다. 하지만 저희 U데미 강좌에서는 모든 것을 아주 세세하게 다루며, 무엇 하나 빼놓고 넘어가지 않습니다. 저희는 재미있는 멀티플레이어 게임 두 개를 차근차근 만들어 나가는 총 20시간 이상의 영상 콘텐츠로 여러분에게 체계적으로 지식을 제공해 드릴 것입니다.

강좌가 끝나면 여러분은:

  • 네트워킹의 난관에 대한 기본 개념(예: 지연 시간, 패킷 드랍, NAT 트래버설 등)을 이해하게 될 것입니다.
  • 언리얼 엔진의 멀티플레이어 기능의 구조를 이해하게 될 것입니다.
  • 로컬 네트워크로 게임 인스턴스를 연결할 수 있게 될 것입니다.
  • 스팀 플러그인과 API를 사용해 플레이어들을 인터넷으로 연결할 수 있게 될 것입니다.
  • 여러분의 게임이 치트를 방지하도록 구성할 수 있을 것입니다.
  • RPC와 프로퍼티 복제를 사용해 머신간의 커뮤니케이트를 할 수 있을 것입니다.
  • 커스템 이동 시스템을 위한 랙 완화 시스템을 빌드할 수 있을 것입니다.
  • 명확한 API 사용을 위해 엔진 코드 읽는 법을 이해할 수 있을 것입니다.

이 강좌는 저희가 첫번째 U데미 강좌에서 100,000명이 넘는 초심자들을 교육했던 경험을 기반으로 구성했습니다. 저희는 이런 경험과 열정을 이번에 새로 진행하는 언리얼 멀티플레이어 강좌에 고스란히 녹여냈습니다. 수강 자격요건으로는 언리얼 엔진을 사용해 간단한 게임을 만들 수 있을 정도면 충분하며, 네트워킹 개념에 대한 사전 지식은 없으셔도 무방합니다.

C++ 멀티플레이어 강좌는 아직 에픽게임즈의 엄격한 내부 검토 절차를 거치지 않았지만, 4,000명 이상의 학생이 강좌에 등록해 5점 만점에 4.8점의 평점을 주었습니다. 이 강좌에서는 네트워킹과 멀티플레이어 게임의 기본 개념에 대해 배우실 수 있습니다.

UdemyC++UE_CourceButton.jpg

이 강좌는 현재 신년 특가로 10달러에 할인중입니다! 서두르세요, 이 특가는 오래가지 않을테니까요!