Survival Kids의 분할 화면(Split-screen) 및 GameShare 네트워킹
요약
KONAMI의 Survival Kids 개발팀이 Unity 6를 사용하여 Nintendo Switch 2용 멀티플레이어 아키텍처를 구축한 사례를 다룹니다. 특히 Netcode for Entities의 한계를 극복하기 위해 가상 입력 플레이어(Virtual Input Player)를 도입하여 분할 화면(Split-screen) 기능을 구현한 기술적 과정을 설명합니다.
핵심 포인트
- Unity 6를 기반으로 Nintendo Switch 2 플랫폼에 최적화된 멀티플레이어 아키텍처 구축
- Netcode for Entities의 클라이언트당 1인 제한을 해결하기 위해 가상 입력 플레이어(Virtual Input Player) 개념 도입
- 분할 화면 구현 시 발생하는 다중 카메라 설정 및 플레이어별 개별 UI 노출 문제 해결
- 로컬 플레이어들의 입력을 하나로 묶어 서버로 전송하는 입력 관리 방식 적용
이번 여름, Unity는 퍼블리셔 파트너인 KONAMI와 긴밀히 협력하여 제작한 첫 번째 게임을 출시했습니다. Survival Kids는 Nintendo Switch™ 2의 출시 당일 타이틀로 선보인 클래식 아동용 게임을 재미있게 업데이트한 작품입니다. 이 게임은 전적으로 Unity 6를 기반으로 구축되었기 때문에, 개발 팀은 새로운 플랫폼에 게임을 출시하기 위해 새로운 소프트웨어를 다루어야 했으며 이는 거대한 도전이었습니다. 게다가 이 게임은 다양한 네트워크 구성에서 즐길 수 있으므로, 프로젝트를 담당하는 소규모 Unity 팀은 이러한 옵션들을 지원할 수 있는 견고한 멀티플레이어 아키텍처 (Multiplayer Architecture)를 구축해야 했습니다.
Survival Kids의 멀티플레이어 네트워킹 이야기 첫 번째 편을 확인해 보세요. 여기에서는 게임의 네트워크 아키텍처 이면에 있는 기본 원리들이 어떻게 결합되었는지 공유합니다. 이 포스트는 해당 기초를 확장하여, 팀이 어떻게 게임의 분할 화면 (Split-screen) 및 Nintendo Switch 2 GameShare 기능을 구축했는지 보여줍니다.
Nintendo Switch는 Nintendo의 상표입니다.
게임의 네트워크 아키텍처에서 발생한 많은 문제들을 해결한 후, 우리는 Netcode for Entities에서 기본적으로 제공되지 않는 분할 화면을 어떻게 구현할지 고민하기 시작했습니다. 이는 또 다른 도전이었습니다. 분할 화면의 경우 반드시 두 명 이상의 플레이어가 존재해야 하지만, 이 플레이어들은 하나의 클라이언트 (Client)에 속해 있습니다.
Netcode for Entities는 클라이언트당 한 명의 플레이어가 있다고 가정합니다. 만약 별도의 콘솔이 연결된 별개의 게임이 있다면, 그것은 한 명의 플레이어를 가집니다. 하지만 상황이 바뀌어 실제로 두 명 또는 세 명의 플레이어가 존재하게 되면, 각 개별 플레이어의 입력을 상위로 보낼 방법이 없습니다. 입력값들은 하나로 묶여서 전송되어야만 합니다.
우리는 결과적으로 아무도 볼 수 없는 가상의 입력 플레이어 (Virtual Input Player)를 만들었습니다. 이는 완전히 보이지 않지만, 최대 4명(비록 최종적으로는 4인 분할 화면을 구현하지는 않았지만)까지의 모든 로컬 플레이어의 입력을 수집합니다. 이 플레이어는 들어오는 모든 입력을 관리한 다음, 매 프레임마다 그 모든 입력을 서버로 전송합니다.
게임 내에서 플레이어들은 각자의 입력을 직접 관리하지 않습니다.
가상의 가상 입력 플레이어(imaginary virtual input player)가 한 프레임 동안의 입력이 무엇인지 그들에게 알려줍니다. 기존에 Netcode for Entities는 플레이어가 자신의 입력을 가져오고, 그 입력을 사용하여 모든 움직임을 수행할 책임이 있다고 가정하지만, 여기에는 움직임은 전혀 수행하지 않으면서 다른 모든 것들에 대한 입력을 보유하는 또 다른 플레이어가 존재합니다.
네트워크 관점에서 분할 화면(Split-screen)은 주요한 과제였습니다. 다중 카메라(multiple cameras) 문제를 피하기 위해, 우리는 카메라가 첫 번째 플레이어와 함께 머무는 동안 두 번째 플레이어가 돌아다니는 방식으로 시작했습니다. 그 부분은 꽤 빠르게 해결되었지만, 그 후 다른 문제들에 직면했습니다. 예를 들어, 두 번째 카메라를 어떻게 설정할 것인가? 어떻게 한 카메라는 화면 왼쪽에, 다른 카메라는 화면 오른쪽에 유지할 것인가? 하는 문제들이었습니다. 우리는 UI 문제도 해결해야 했는데, 왜냐하면 오직 한 명의 플레이어만 볼 수 있는 UI가 상당히 많기 때문입니다. 예를 들어, 한 플레이어가 통나무 앞에 있다면, 그들에게는 "이 통나무를 집으려면 X를 누르세요"라고 적힌 작은 프롬프트 버튼이 보이겠지만, 당연히 다른 플레이어에게는 그것이 보이지 않기를 원할 것입니다.
우리는 다른 플레이어가 근처에 있더라도 그 UI가 보이지 않도록 숨기는 방법을 찾아내야 했습니다. 우리는 이를 위해 레이어(layers)를 사용했지만, 우리의 해결책은 네트워크보다는 UI와 더 관련이 있었습니다. 우리는 더 나은 게임플레이 경험을 위해, 비록 큰 화면이라 할지라도 로컬 플레이어는 두 명의 분할 화면 플레이어로 게임을 고정하기로 최종 결정했습니다. 내부적으로는 분할 화면에서 4명까지 구현할 수 있었고, 이를 꽤 오랫동안 유지했는데, 이는 성능을 스트레스 테스트(stress-testing)하기에 아주 좋은 방법이었기 때문입니다. 플레이어가 추가될 때마다 처리량(processing)과 렌더링(rendering)이 조금씩 늘어나고, 시뮬레이션해야 할 플레이어가 한 명 더 추가되기 때문입니다.
Nintendo Switch 2 개발 과정 중의 기능 중 하나는 GameShare입니다.
실질적으로는 다른 콘솔로 비디오 피드 (video feed)를 보내는 것과 같습니다. 네트워크 관점에서 보면 사실상 분할 화면 (split screen)과 다를 바 없지만, 시스템이 화면에 렌더링 (rendering)하는 대신 하나의 카메라를 다른 콘솔로 보내는 차이가 있습니다. 저희의 4인용 분할 화면은 GameShare 모드에 접근하는 방식의 기초가 되었습니다. 성능이 허용되고 해당 콘솔로 비디오를 스트리밍 (streaming)할 수 있는 한, 원하는 만큼 많은 플레이어를 연결할 수 있었습니다. 저희가 4인용 분할 화면을 원하지 않았던 주된 이유는 사실상 화면 크기 때문이었습니다. 거대한 TV가 있지 않는 한, 화면 창들을 보기가 정말 어렵습니다. 하지만 각자의 콘솔을 가지고 있다면, 비디오를 그쪽으로 스트리밍할 수 있습니다.
저희는 GameShare에서 추가적인 세 번째 플레이어를 지원할 수 있도록 기존의 2인용 분할 화면 모드와 차별화하기 위해 강력하게 밀어붙였습니다. 플레이어들에게 훌륭한 경험과 부드러운 성능을 제공하면서도, 호스트 (host) 한 명과 게스트 (guest) 두 명을 둘 수 있습니다. 저희는 그 부분에 있어서 기준을 낮출 의사가 없었지만, 분할 화면 아키텍처 (architecture)를 사용하여 GameShare를 구동할 수 있었습니다.
저희가 추가한 정말 유용한 기능 중 하나는 디버그 명령 (debug command)이었습니다. 저희는 개발자 메뉴 (dev menu)를 가지고 있어서, 버튼을 눌러 메뉴를 호출한 다음 명령어를 입력할 수 있습니다. 이는 수많은 디버그 작업을 실행할 수 있게 해주었기에 매우 유용했습니다. 이 기능들은 모두 최종 게임에서 컴파일 (compiled)되어 제외되므로, 당연히 사람들이 구매해서 플레이하는 최종 게임에서는 아무도 이를 수행할 수 없습니다. 하지만 분할 화면 모드 중 하나로 메인 플레이어를 복제할 수 있는 기능이 있었습니다. 이를 통해 하나의 컨트롤러 (controller)로 두 플레이어를 조작하는 분할 화면을 구현할 수 있었습니다. 이는 주변에 수많은 컨트롤러를 둘 필요 없이 분할 화면을 테스트할 수 있는 아주 좋은 방법이었으며, 테스트를 더 용이하게 만들어 주었습니다.
분할 화면 설정은 또한 저희가 작업한 모든 일반적인 네트워킹 코드 (networking code)를 효과적으로 실행했습니다. 플레이어들이 서로 분리되어 있었기 때문에, 서버 (server)는 온라인 게임이 어떻게 작동하는지 보여주기 위한 정보를 전송했습니다.
하지만 에디터 (Editor)에서 다른 컨트롤러를 사용하여 분할 화면 (split screen) 모드를 실행함으로써, 플레이어를 다른 클라이언트 (client)에 연결하지 않고도 멀티플레이어 (multiplayer) 모드에서 코드가 제대로 작동하는지 테스트하는 것도 가능합니다. 분할 화면을 일반적인 온라인 게임의 대리 (proxy)로 사용하여 코드를 테스트할 수 있기 때문에, 새로운 빌드 (build)를 할 필요가 없습니다. 프로젝트의 거의 마지막 단계까지 사용하지는 않았지만, 정말 유용하다고 느낀 Unity 도구가 두 가지 더 있었습니다. Unity 6에는 별도의 플레이어 빌드 없이도 테스트를 가능하게 하는 새로운 멀티플레이어 플레이 모드 (Multiplayer Play Mode) 도구가 포함되어 있습니다. 에디터를 열고 깨끗한 플레이어 빌드를 만드는 데는 아트 (art)와 기타 정보가 너무 많아서 한 시간 이상이 걸리며, 따라서 원격 플레이어 (remote player)로 코드를 테스트한다는 것은 최소한 그만큼의 시간을 기다려야 함을 의미합니다. 이는 반복 작업 (iteration)에 그리 좋지 않습니다. 하지만 멀티플레이어 플레이 모드를 사용하면 에디터의 또 다른 가상 버전과 같은 별도의 창을 효과적으로 띄우고 그 방식으로 연결할 수 있습니다. Netcode for Entities 또한 좋지 않은 네트워크 연결을 시뮬레이션하기 위한 플레이 모드 (Play Mode) 도구를 갖추고 있습니다. 특정 수준의 핑 (ping)을 지정하고 시뮬레이션할 수 있는데, 예를 들어 300밀리초의 핑을 설정하여 공항에서 휴대폰을 노트북에 테더링하여 게임에 연결한 친구와 플레이할 때와 같은 정말 끔찍한 왕복 시간 (round trip)을 시뮬레이션할 수 있습니다. 그런 다음 에디터에서 이를 테스트하여 얼마나 지연 (laggy)되거나 불안정한지 확인할 수 있습니다. 때때로 데이터가 손실되거나 패킷 (packet)이 드롭되는 네트워크 연결에서는 제대로 작동하지 않을 때가 있는데, 우리는 이를 쉽게 시뮬레이션할 수 있었습니다. 이러한 테스트는 항상 이루어졌습니다. 한동안 우리는 시뮬레이터 (simulator)를 끈 상태로는 아무도 에디터에서 플레이할 수 없다는 규칙을 세웠습니다. 우리의 플레이어 중 그 누구도 완벽한 연결 상태에서 플레이하지 않을 것이기 때문에, 모두가 반드시 어떤 종류의 시뮬레이션된 지연 (simulated lag) 상태에서 플레이해야 했습니다.
그렇게 함으로써, 우리는 초고속 사무실 광대역 (broadband) 네트워크가 대표적인 사례라고 스스로를 속이는 일이 결코 없도록 할 수 있었습니다. 결국, 이 모든 테스트는 결실을 보았습니다. 우리는 매우 상이한 네트워크 및 멀티플레이어 (multiplayer) 설정 환경에서도 60 fps로 부드럽고 성능이 뛰어난 게임을 제공할 수 있었습니다. 몇 주 전 게임이 출시된 이후, 우리는 플레이어들이 Lobby 및 Relay를 통해 지속적으로 온라인에 접속하는 것을 확인하고 있으며, 이들이 가정 내 네트워크 환경에 관계없이 원활하고 견고한 게임 경험을 즐기기를 희망합니다. Survival Kids 제작 과정을 심층 분석하는 당사 블로그 시리즈의 다른 회차들도 확인해 보세요: - "Survival Kids의 그래픽 및 렌더링 (rendering) 팁" - "Survival Kids의 레벨 레이아웃 (level layout) 및 지형 워크플로 (terrain workflows)" - "Survival Kids 멀티플레이어 네트워크 인프라 (network infrastructure) 내부 들여다보기" Unity로 제작된 프로젝트에 대해 더 자세히 알고 싶다면, Resources 페이지를 방문하세요.
AI 자동 생성 콘텐츠
본 콘텐츠는 Unity Blog의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기