paint-brush
전쟁 로봇 10주년을 기념하고 기술적 관점에서 성찰~에 의해@pauxi
3,667 판독값
3,667 판독값

전쟁 로봇 10주년을 기념하고 기술적 관점에서 성찰

~에 의해 Paul Xi31m2024/04/30
Read on Terminal Reader

너무 오래; 읽다

이 게시물에서 우리는 10년 동안 War Robots의 기술적 측면을 살펴봅니다. 즉, 멋진 점, 문제, 실험, 게임 리마스터링 등이 있습니다!
featured image - 전쟁 로봇 10주년을 기념하고 기술적 관점에서 성찰
Paul Xi HackerNoon profile picture
0-item
1-item


War Robots는 올해 4월에 창립 10주년을 맞이합니다! 그리고 오늘날까지 우리는 플레이어를 위한 새로운 기능을 출시할 뿐만 아니라 기술적으로 개선하는 등 계속해서 개발하고 지원하고 있습니다.


이 기사에서 우리는 이 대규모 프로젝트의 기술 개발에 있어 수년간의 경험에 대해 논의할 것입니다. 하지만 먼저 현재 프로젝트의 스냅샷은 다음과 같습니다.


  • 수십만 명의 DAU(일일 활성 사용자)
  • 수억 건의 설치
  • 수만 개의 동시 12인 매치
  • 4가지 주요 플랫폼(iOS, Android, Steam, Amazon)에서 사용 가능
  • Android 및 PC를 포함한 수만 대의 지원 장치
  • 수백 대의 서버
  • 약 20명의 클라이언트 개발자, 9명의 서버 개발자, 8명으로 구성된 교차 프로젝트 개발팀, 3명의 DevOps
  • 약 150만 줄의 클라이언트측 코드
  • 2014년 버전 4부터 Unity를 사용하고 있으며 현재 2024년 버전 2022 LTS를 사용하고 있습니다.


이러한 유형의 프로젝트 기능을 유지하고 더욱 높은 품질의 개발을 보장하려면 즉각적인 제품 작업에만 집중하는 것만으로는 충분하지 않습니다. 기술적 조건을 개선하고, 개발을 단순화하고, 새로운 콘텐츠 생성과 관련된 프로세스를 포함한 프로세스를 자동화하는 것도 중요합니다. 또한, 우리는 사용 가능한 사용자 장치의 변화하는 시장에 지속적으로 적응해야 합니다.


이 텍스트는 Pixonic(MY.GAMES)의 개발 부서 책임자인 Pavel Zinov와 War Robots의 수석 개발자인 Dmitry Chetverikov와의 인터뷰를 바탕으로 작성되었습니다.


시작

2014년으로 돌아가 보겠습니다. War Robots 프로젝트는 처음에 소규모 팀에 의해 만들어졌으며 모든 기술 솔루션은 신속한 개발 및 시장에 새로운 기능 제공이라는 패러다임에 적합했습니다. 당시 회사에는 전용 서버를 호스팅할 대규모 리소스가 없었기 때문에 War Robots는 P2P 로직을 기반으로 하는 네트워크 멀티 플레이어로 시장에 진출했습니다.


Photon Cloud는 클라이언트 간 데이터 전송에 사용되었습니다. 이동, 사격 또는 기타 명령 등 각 플레이어 명령은 별도의 RPC를 사용하여 Photon Cloud 서버로 전송되었습니다. 전용 서버가 없었기 때문에 게임에는 모든 플레이어의 매치 상태 신뢰성을 담당하는 마스터 클라이언트가 있었습니다. 동시에 나머지 플레이어는 로컬 클라이언트에서 전체 게임 상태를 완전히 처리했습니다.


예를 들어, 움직임에 대한 검증은 없었습니다. 로컬 클라이언트는 적절하다고 판단되는 대로 로봇을 움직였고, 이 상태는 마스터 클라이언트로 전송되었으며, 마스터 클라이언트는 무조건 이 상태를 믿고 이를 매치의 다른 클라이언트에게 전달했습니다. 각 클라이언트는 독립적으로 전투 로그를 보관하고 경기가 끝나면 서버로 전송하며, 서버는 모든 플레이어의 로그를 처리하여 보상을 지급하고 경기 결과를 모든 플레이어에게 전송합니다.


우리는 플레이어 프로필에 대한 정보를 저장하기 위해 특별한 프로필 서버를 사용했습니다. 이는 Cassandra 데이터베이스를 갖춘 여러 서버로 구성되었습니다. 각 서버는 Tomcat의 간단한 앱 서버였으며 클라이언트는 HTTP를 통해 상호 작용했습니다.


초기 접근 방식의 단점

게임플레이에 사용된 접근 방식에는 여러 가지 단점이 있었습니다. 물론 팀은 이에 대해 알고 있었지만 개발 속도와 최종 제품의 시장 출시 속도로 인해 많은 타협이 이루어져야 했습니다.


이러한 단점 중 가장 먼저 마스터 클라이언트 연결 품질이 있었습니다. 클라이언트의 네트워크 상태가 좋지 않으면 경기에 참여하는 모든 플레이어가 지연을 경험하게 됩니다. 그리고 마스터 클라이언트가 매우 강력한 스마트폰에서 실행되고 있지 않은 경우, 높은 부하로 인해 게임에서도 데이터 전송이 지연되는 현상이 발생했습니다. 따라서 이번 경우에는 마스터 클라이언트 외에 다른 플레이어들도 피해를 입었습니다.


두 번째 단점은 이 아키텍처가 사기꾼에게 문제가 발생하기 쉽다는 것입니다. 최종 상태가 마스터 클라이언트에서 전송되었으므로 이 클라이언트는 재량에 따라 많은 일치 매개변수를 변경할 수 있습니다(예: 일치에서 캡처된 영역 수 계산).


셋째, Photon Cloud의 매치메이킹 기능에 문제가 있습니다. Photon Cloud 매치메이킹 룸에서 가장 오래된 플레이어가 마스터 클라이언트가 되며, 매치메이킹 중에 문제가 발생하면(예: 연결 끊김) 그룹 생성에 부정적인 영향을 미칩니다. 관련 재미있는 사실: 그룹을 매치에 보낸 후 Photon Cloud의 매치메이킹이 종료되는 것을 방지하기 위해 한동안 사무실에 간단한 PC를 설치했는데 이는 항상 매치메이킹을 지원했기 때문에 Photon Cloud와의 매치메이킹은 실패할 수 없었습니다. .


어떤 시점에서 문제와 지원 요청의 수가 임계 수준에 이르렀고, 우리는 게임의 기술 아키텍처를 발전시키는 것에 대해 진지하게 생각하기 시작했습니다. 이 새로운 아키텍처는 인프라 2.0이라고 불렸습니다.


인프라 2.0으로의 전환

이 아키텍처의 주요 아이디어는 전용 게임 서버를 만드는 것이었습니다. 당시 클라이언트 팀에는 광범위한 서버 개발 경험을 갖춘 프로그래머가 부족했습니다. 그러나 회사는 AppMetr이라고 불리는 서버 기반의 고부하 분석 프로젝트를 동시에 진행하고 있었습니다. 이 팀은 하루에 수십억 개의 메시지를 처리하는 제품을 만들었으며 서버 솔루션의 개발, 구성 및 올바른 아키텍처에 대한 광범위한 전문 지식을 보유하고 있었습니다. 그래서 해당 팀의 일부 구성원이 인프라 2.0 작업에 참여했습니다.


2015년에는 상당히 짧은 기간 내에 Windows Server에서 실행되는 Photon Server SDK 프레임워크로 래핑된 .NET 서버가 생성되었습니다. 우리는 Photon Cloud를 포기하고 클라이언트 프로젝트에 Photon Server SDK 네트워크 프레임워크만 유지하기로 결정했으며 매치메이킹을 위해 클라이언트와 해당 서버를 연결하기 위한 마스터 서버를 만들었습니다. 일부 로직이 클라이언트에서 전용 게임 서버로 이동되었습니다. 특히, 기본적인 손상 검증 기능이 도입되었으며, 서버에 경기 결과 계산 기능이 추가되었습니다.



마이크로서비스의 등장

인프라 2.0을 성공적으로 만든 후 우리는 서비스의 책임을 분리하는 쪽으로 계속 나아가야 한다는 것을 깨달았습니다. 그 결과 마이크로서비스 아키텍처가 탄생했습니다. 이 아키텍처에서 생성된 첫 번째 마이크로서비스는 클랜이었습니다.


거기에서 별도의 통신 서비스가 나타났으며 이는 마이크로서비스 간 데이터 전송을 담당했습니다. 클라이언트는 게임 서버의 메타 메커니즘을 담당하는 "행거"와 연결을 설정하고 Photon Cloud를 통해 UDP를 사용하여 API 요청(서비스와 상호 작용하기 위한 단일 진입점)을 만드는 방법을 배웠습니다. 점차적으로 서비스 수가 증가했고 그 결과 매치메이킹 마이크로서비스를 리팩터링했습니다. 이를 통해 뉴스 기능인 Inbox가 탄생했습니다.


클랜을 만들 때 플레이어들이 게임에서 서로 소통하고 싶어한다는 것은 분명했습니다. 일종의 채팅이 필요했기 때문입니다. 이것은 원래 Photon Chat을 기반으로 생성되었지만 마지막 클라이언트 연결이 끊기자마자 전체 채팅 기록이 삭제되었습니다. 따라서 우리는 이 솔루션을 Cassandra 데이터베이스를 기반으로 하는 별도의 마이크로서비스로 변환했습니다.


인프라 4.0 및 서버 위치

새로운 마이크로서비스 아키텍처를 통해 우리는 서로 독립적인 수많은 서비스를 편리하게 관리할 수 있었습니다. 이는 전체 시스템을 수평적으로 확장하고 가동 중지 시간을 방지한다는 의미였습니다.


우리 게임에서는 서버를 일시 중지할 필요 없이 업데이트가 이루어졌습니다. 서버 프로필은 여러 버전의 클라이언트와 호환되었으며 게임 서버의 경우 항상 클라이언트의 이전 버전과 새 버전을 위한 서버 풀이 있습니다. 이 풀은 애플리케이션 스토어에서 새 버전이 출시된 후 점차적으로 이동했습니다. 게임 서버는 이전 버전에서 시간이 지남에 따라 사라졌습니다. 현재 인프라의 일반적인 개요는 인프라 4.0이라고 하며 다음과 같습니다.



아키텍처를 변경하는 것 외에도 우리는 서버가 전 세계의 플레이어를 보호해야 하기 때문에 서버를 어디에 배치할지에 대한 딜레마에 직면했습니다. 처음에는 여러 가지 이유로 Amazon AWS에 많은 마이크로서비스가 배치되었습니다. 특히 이 시스템이 확장 측면에서 제공하는 유연성 때문에 이는 게임 트래픽이 급증하는 순간(예: 매장에 소개되거나 UA를 높이기 위해). 게다가 그 당시에는 좋은 네트워크 품질과 외부 세계와의 연결을 제공하는 좋은 호스팅 제공업체를 아시아에서 찾기가 어려웠습니다.


Amazon AWS의 유일한 단점은 높은 비용이었습니다. 따라서 시간이 지남에 따라 많은 서버가 자체 하드웨어, 즉 전 세계 데이터 센터에서 임대하는 서버로 이전되었습니다. 그럼에도 불구하고 Amazon AWS는 끊임없이 변화하고 안정성이 충분히 보장되지 않는 코드(특히 리그, 클랜, 채팅 및 뉴스 서비스용 코드)의 개발을 허용하므로 아키텍처의 중요한 부분으로 남아 있습니다. 테스트. 하지만 마이크로서비스가 안정적이라는 것을 깨닫자마자 우리는 이를 자체 시설로 옮겼습니다. 현재 모든 마이크로서비스는 하드웨어 서버에서 실행됩니다.


장치 품질 관리 및 기타 지표

2016년에는 게임 렌더링에 중요한 변화가 있었습니다. 전투에서 모든 기계에 대한 단일 텍스처 아틀라스를 갖춘 Ubershaders 개념이 등장하여 드로우 콜 횟수가 크게 줄어들고 게임 성능이 향상되었습니다.


우리 게임이 수만 가지의 다양한 장치에서 플레이되고 있다는 것이 분명해졌으며 각 플레이어에게 가능한 최상의 게임 조건을 제공하고 싶었습니다. 따라서 우리는 기본적으로 플레이어의 장치를 분석하고 특정 게임 또는 렌더링 기능을 활성화(또는 비활성화)하는 파일인 Quality Manager를 만들었습니다. 게다가 이 기능을 통해 특정 장치 모델까지 이러한 기능을 관리할 수 있어 플레이어가 겪고 있는 문제를 신속하게 해결할 수 있었습니다.


서버에서 Quality Manager 설정을 다운로드하고 현재 성능에 따라 장치의 품질을 동적으로 선택할 수도 있습니다. 논리는 매우 간단합니다. 품질 관리자의 전체 본문은 블록으로 나뉘며 각 블록은 성능의 일부 측면을 담당합니다. (예를 들어 그림자의 품질이나 앤티앨리어싱 등) 사용자의 성능이 저하되면 시스템은 블록 내부의 값을 변경하고 성능을 향상시킬 수 있는 옵션을 선택하려고 시도합니다. 조금 후에 Quality Manager의 발전에 대해 다시 설명하겠지만, 이 단계에서는 구현 속도가 상당히 빨랐고 필요한 수준의 제어가 제공되었습니다.


그래픽 개발이 계속되면서 품질 관리자에 대한 작업도 필요했습니다. 이제 이 게임에는 그래픽 프로그래머가 전적으로 구현한 계단식 동적 그림자 기능이 포함되어 있습니다.


점차적으로 프로젝트 코드에 꽤 많은 엔터티가 등장했기 때문에 우리는 엔터티의 수명을 관리하고 다양한 기능에 대한 액세스를 제한하는 것이 좋을 것이라고 결정했습니다. 이는 게임 컨텍스트가 변경될 때 많은 리소스가 지워지지 않았기 때문에 격납고와 전투 코드를 분리하는 데 특히 중요했습니다. 우리는 다양한 IoC 종속성 관리 컨테이너를 탐색하기 시작했습니다. 특히 StrangeIoC 솔루션을 살펴보았습니다. 당시에는 솔루션이 다소 번거로워 보였기 때문에 프로젝트에 간단한 DI를 구현했습니다. 격납고와 전투 컨텍스트도 도입했습니다.


또한 우리는 프로젝트의 품질 관리 작업을 시작했습니다. 프로덕션 환경에서 충돌, ANR, 예외를 식별하기 위해 FirebaseCrashlytics가 게임에 통합되었습니다.


AppMetr이라는 내부 분석 솔루션을 사용하여 고객 상태를 정기적으로 모니터링하고 릴리스 중 변경 사항을 비교하는 데 필요한 대시보드를 만들었습니다. 또한 프로젝트 품질을 향상하고 코드 변경에 대한 신뢰도를 높이기 위해 자동 테스트를 연구하기 시작했습니다.


자산의 수가 늘어나고 콘텐츠에 고유한 버그가 늘어나면서 자산을 정리하고 통합해야겠다는 생각을 하게 되었습니다. 기계의 빌드가 각각 고유했기 때문에 이는 특히 기계의 경우에 해당됩니다. 이를 위해 우리는 Unity에서 도구를 만들었고 이를 사용하여 주요 필수 구성 요소로 기계 인형을 만들었습니다. 이는 게임 디자인 부서가 이를 쉽게 편집할 수 있다는 것을 의미했으며 이것이 우리가 처음으로 작업을 기계와 통합하기 시작한 방법이었습니다.


더 많은 플랫폼

프로젝트는 계속 성장했고 팀은 이를 다른 플랫폼에 출시하는 것을 고려하기 시작했습니다. 또한, 또 다른 점은 당시 일부 모바일 플랫폼의 경우 게임이 플랫폼의 기본 기능을 최대한 많이 지원하여 게임이 등장할 수 있도록 하는 것이 중요했습니다. 그래서 우리는 Apple TV용 War Robots의 실험 버전과 Apple Watch용 동반 앱 작업을 시작했습니다.


또한 2016년에는 Amazon AppStore라는 새로운 플랫폼에서 게임을 출시했습니다. 기술적인 측면에서는 애플처럼 디바이스 라인이 통일되어 있다는 점에서 이 플랫폼이 독특하지만, 이 라인의 위력은 보급형 안드로이드 수준이다. 이를 염두에 두고 이 플랫폼을 출시할 때 메모리 사용과 성능을 최적화하기 위해 아틀라스, 텍스처 압축 작업 등 상당한 작업이 수행되었습니다. 로그인 및 업적을 위한 Game Center와 유사한 Amazon 결제 시스템이 클라이언트에 통합되었으므로 플레이어 로그인 작업 흐름이 다시 실행되고 첫 번째 업적이 시작되었습니다.


동시에 클라이언트 팀이 처음으로 Unity 에디터용 도구 세트를 개발했으며 이를 통해 엔진에서 게임 내 비디오를 촬영할 수 있게 되었다는 점도 주목할 만합니다. 이를 통해 마케팅 부서에서 자산 작업, 전투 제어, 카메라 활용을 통해 청중이 매우 좋아하는 비디오를 만드는 것이 더 쉬워졌습니다.


사기꾼과의 싸움

Unity, 특히 서버의 물리 엔진이 없기 때문에 대부분의 경기는 플레이어 장치에서 계속 에뮬레이트되었습니다. 이로 인해 사기꾼과의 문제가 지속되었습니다. 정기적으로 우리 지원팀은 사용자로부터 부정 행위자 동영상을 통해 피드백을 받았습니다. 그들은 편리한 시간에 속도를 내고, 맵을 돌아다니고, 모퉁이에서 다른 플레이어를 죽이고, 불멸자가 되는 등의 행위를 했습니다.


이상적으로는 모든 메커니즘을 서버로 이전하는 것입니다. 그러나 게임이 지속적으로 개발 중이고 이미 상당한 양의 레거시 코드가 축적되어 있다는 사실 외에도 권한 있는 서버를 사용하는 접근 방식에는 다른 단점도 있을 수 있습니다. 예를 들어 인프라에 대한 부하가 증가하고 더 나은 인터넷 연결에 대한 요구가 증가합니다. 대부분의 사용자가 3G/4G 네트워크에서 플레이했다는 점을 고려하면 이 접근 방식은 분명하지만 문제에 대한 효과적인 해결책은 아니었습니다. 팀 내에서 부정 행위자를 퇴치하기 위한 대안적인 접근 방식으로 우리는 "정족수"를 만드는 새로운 아이디어를 생각해 냈습니다.


Quorum은 피해를 확인할 때 다양한 플레이어의 여러 시뮬레이션을 비교할 수 있는 메커니즘입니다. 피해를 입는 것은 게임의 주요 기능 중 하나이며 사실상 나머지 상태가 이에 따라 달라집니다. 예를 들어, 상대방을 파괴하면 상대방은 비컨을 탈취할 수 없습니다.


이 결정의 아이디어는 다음과 같습니다. 각 플레이어는 여전히 전 세계를 시뮬레이션하고(다른 플레이어를 쏘는 것을 포함하여) 결과를 서버로 보냅니다. 서버는 모든 플레이어의 결과를 분석해 플레이어가 최종적으로 피해를 입었는지, 어느 정도 피해를 입었는지 판단했다. 우리의 경기에는 12명이 참여하므로 서버가 피해를 입었다고 간주하려면 이 사실이 7명의 플레이어의 로컬 시뮬레이션 내에 등록되는 것으로 충분합니다. 그런 다음 이러한 결과는 추가 검증을 위해 서버로 전송됩니다. 개략적으로 이 알고리즘은 다음과 같이 표현될 수 있습니다.



이 계획을 통해 우리는 전투에서 스스로를 죽일 수 없게 만드는 치터의 수를 크게 줄일 수 있었습니다. 다음 그래프는 이러한 사용자에 대한 불만 건수뿐만 아니라 서버에서 피해 계산 기능을 활성화하고 피해 정족수를 활성화하는 단계를 보여줍니다.



이 피해 처리 메커니즘은 오랫동안 부정 행위 문제를 해결했습니다. 서버에 물리적인 결함이 있음에도 불구하고(따라서 표면 지형 및 우주에서 로봇의 실제 위치 등을 고려할 수 없음), 모든 고객에 대한 시뮬레이션과 그들의 합의는 누가 누구에게 어떤 조건에서 피해를 입혔는지에 대한 명확한 이해를 제공했습니다.


프로젝트의 추가 개발

시간이 지남에 따라 동적 그림자 외에도 Unity 포스트 프로세싱 스택과 배치 렌더링을 사용하여 게임에 포스트 효과를 추가했습니다. 후처리 효과를 적용한 결과 향상된 그래픽의 예는 아래 그림에서 볼 수 있습니다.



디버그 빌드에서 무슨 일이 일어나고 있는지 더 잘 이해하기 위해 우리는 로깅 시스템을 만들고 내부 테스터로부터 로그를 수집하고 버그의 원인을 더 쉽게 찾을 수 있는 내부 인프라에 로컬 서비스를 배포했습니다. 이 도구는 여전히 QA의 플레이 테스트에 사용되며 작업 결과는 Jira의 티켓에 첨부됩니다.


또한 자체 작성 패키지 관리자를 프로젝트에 추가했습니다. 처음에 우리는 다양한 패키지와 외부 플러그인(이미 프로젝트에 충분한 수가 축적되어 있음)을 사용하여 작업을 개선하고 싶었습니다. 그러나 당시에는 Unity의 기능이 충분하지 않았기 때문에 우리 내부 플랫폼 팀은 패키지 버전 관리, NPM을 사용한 스토리지, GitHub에 링크를 추가하는 것만으로 프로젝트에 패키지를 연결하는 기능을 갖춘 자체 솔루션을 개발했습니다. 우리는 여전히 네이티브 엔진 솔루션을 사용하고 싶었기 때문에 Unity 동료들과 상의했고, Unity가 2018년에 패키지 관리자를 출시했을 때 우리의 아이디어 중 상당수가 Unity의 최종 솔루션에 포함되었습니다.


우리는 게임을 사용할 수 있는 플랫폼의 수를 계속해서 확장했습니다. 결국 키보드와 마우스를 지원하는 플랫폼인 페이스북 게임룸이 등장했다. 이는 사용자가 PC에서 애플리케이션을 실행할 수 있도록 하는 Facebook(Meta)의 솔루션입니다. 본질적으로 Steam 상점 아날로그입니다. 물론 Facebook 사용자는 매우 다양하며 Facebook Gameroom은 주로 게임이 아닌 장치를 중심으로 수많은 장치에서 출시되었습니다. 그래서 우리는 주 관객층의 PC에 부담을 주지 않기 위해 게임 내 모바일 그래픽을 그대로 유지하기로 결정했습니다. 기술적 관점에서 볼 때 게임에 필요한 유일한 중요한 변경 사항은 SDK, 결제 시스템의 통합, 기본 Unity 입력 시스템을 사용한 키보드 및 마우스 지원이었습니다.


기술적으로는 Steam용 게임 빌드와 거의 다르지 않았지만, 플랫폼은 브라우저 외에는 아무것도 실행할 수 없는 매우 간단한 장치를 사용하는 캐주얼 플레이어를 위한 장소로 포지셔닝되었기 때문에 장치의 품질이 상당히 낮았습니다. 페이스북은 상당히 큰 시장에 진출하기를 희망했습니다. 이러한 장치의 리소스는 제한되어 있었고, 특히 플랫폼에는 지속적인 메모리 및 성능 문제가 있었습니다.


나중에 플랫폼이 문을 닫았고 우리는 가능한 곳인 Steam으로 플레이어를 이전했습니다. 이를 위해 우리는 플랫폼 간 계정 전송을 위한 코드가 포함된 특수 시스템을 개발했습니다.


VR로 전쟁 로봇을 사용해 보세요

2017년 주목할만한 또 다른 이벤트는 최초의 노치 스마트폰인 iPhone X의 출시입니다. 당시 Unity는 노치가 있는 장치를 지원하지 않았기 때문에 UI가 휴대폰 화면의 다양한 안전 영역을 피하고 크기를 조정하도록 하는 UnityEngine.Screen.safeArea 매개변수를 기반으로 하는 맞춤형 솔루션을 만들어야 했습니다.


또한, 2017년에 우리는 다른 것을 시도하기로 결정했습니다. 바로 Steam에서 VR 버전의 게임을 출시하는 것이었습니다. 개발은 약 6개월 동안 진행되었으며 당시 사용 가능한 모든 헬멧(Oculus, HTC Vive 및 Windows Mixed Reality)에 대한 테스트가 포함되었습니다. 이 작업은 Oculus API와 Steam API를 사용하여 수행되었습니다. 또한, PS VR 헤드셋용 데모 버전과 MacOS 지원도 준비되었습니다.


기술적인 관점에서는 PS VR의 경우 60FPS, HTC Vive의 경우 90FPS 등 안정적인 FPS를 유지하는 것이 필요했습니다. 이를 달성하기 위해 표준 절두체 및 폐색과 재투영(일부 프레임이 이전 프레임을 기반으로 생성되는 경우) 외에도 자체 스크립팅된 Zone Culling이 사용되었습니다.


멀미 문제를 해결하기 위해 흥미롭고 창의적이고 기술적인 솔루션이 채택되었습니다. 플레이어가 로봇 조종사가 되어 조종석에 앉았습니다. 객실은 정적 요소였기 때문에 뇌는 이를 세계에서 일종의 상수로 인식하여 공간에서의 움직임이 매우 잘 작동했습니다.


또한 이 게임에는 해당 버전의 Unity에서 Cinemachine을 아직 사용할 수 없었기 때문에 여러 가지 별도의 트리거, 스크립트 및 자체 타임라인을 개발해야 하는 시나리오도 있었습니다.


각 무기에 대해 타겟팅, 잠금, 추적 및 자동 조준 로직이 처음부터 작성되었습니다.


해당 버전은 Steam에 출시되었으며 플레이어들로부터 호평을 받았습니다. 그러나 Kickstarter 캠페인 이후, VR용 본격적인 PvP 슈팅 게임의 개발은 기술적인 위험과 이러한 프로젝트에 대한 시장의 준비가 부족했기 때문에 프로젝트 개발을 계속하지 않기로 결정했습니다.


첫 번째 심각한 버그 처리

우리는 게임의 기술적 구성 요소를 개선하고 새로운 메커니즘과 플랫폼을 개발하고 개발하는 동안 게임에서 첫 번째 심각한 버그를 발견했습니다. 이는 새로운 프로모션을 출시할 때 수익에 부정적인 영향을 미쳤습니다. 문제는 '가격' 버튼이 '상품'으로 잘못 현지화되었다는 것입니다. 이에 대부분의 플레이어들은 혼란스러워하며 실제 화폐로 구매한 후 환불을 요청했습니다.


기술적인 문제는 당시에는 모든 현지화가 게임 클라이언트에 내장되어 있었다는 점이었습니다. 이 문제가 발생했을 때 우리는 현지화 업데이트를 가능하게 하는 솔루션 작업을 더 이상 미룰 수 없다는 것을 깨달았습니다. 이것이 CDN에 현지화 파일을 자동으로 업로드하는 TeamCity의 프로젝트와 같은 CDN 및 관련 도구를 기반으로 하는 솔루션이 만들어진 방법입니다.


이를 통해 우리가 사용한 서비스(POEditor)에서 현지화를 다운로드하고 원시 데이터를 CDN에 업로드할 수 있었습니다.

그 후 서버 프로필은 현지화 데이터에 해당하는 각 클라이언트 버전에 대한 링크 설정을 시작했습니다. 애플리케이션이 시작되면 프로필 서버가 이 링크를 클라이언트에 보내기 시작했고 이 데이터가 다운로드되어 캐시되었습니다.


데이터를 활용한 작업 최적화

2018년으로 넘어가 보겠습니다. 프로젝트가 성장함에 따라 서버에서 클라이언트로 전송되는 데이터의 양도 늘어났습니다. 서버에 접속할 때 잔액, 현재 설정 등에 관한 꽤 많은 데이터를 다운로드해야 했습니다.


현재 데이터는 XML 형식으로 표시되었으며 표준 Unity 직렬 변환기에 의해 직렬화되었습니다.

클라이언트를 시작할 때, 프로필 서버 및 게임 서버와 통신할 때 상당히 많은 양의 데이터를 전송하는 것 외에도 플레이어 장치는 현재 잔액을 저장하고 직렬화/역직렬화하는 데 많은 메모리를 소비했습니다.


애플리케이션의 성능과 시작 시간을 향상시키기 위해서는 대체 프로토콜을 찾기 위한 R&D가 필요하다는 것이 분명해졌습니다.


테스트 데이터에 대한 연구 결과가 다음 표에 표시되어 있습니다.


규약

크기

할당

시간

XML

2.2MB

18.4MiB

518.4ms

MessagePack(무계약)

1.7MB

2MiB

32.35ms

MessagePack(str 키)

1.2MB

1.9MiB

25.8ms

MessagePack(정수 키)

0.53MB

1.9

16.5

FlatBuffer

0.5MB

216B

0ms / 12ms / 450KB


결과적으로, 특히 정수 키와 함께 MessagePack을 사용할 때 유사한 출력 결과를 갖는 FlatBuffer로 전환하는 것보다 마이그레이션이 더 저렴했기 때문에 MessagePack 형식을 선택했습니다.


FlatBuffers(및 프로토콜 버퍼 포함)의 경우 별도의 언어로 메시지 형식을 설명하고, C# 및 Java 코드를 생성하고, 생성된 코드를 애플리케이션에서 사용해야 합니다. 클라이언트와 서버를 리팩토링하는 데 추가 비용이 발생하는 것을 원하지 않았기 때문에 MessagePack으로 전환했습니다.


전환은 거의 원활하게 진행되었으며 첫 번째 릴리스에서는 새 시스템에 문제가 없다고 확신할 때까지 XML로 롤백하는 기능을 지원했습니다. 새로운 솔루션은 우리의 모든 작업을 다루었습니다. 클라이언트 로딩 시간을 크게 줄이고 서버에 요청할 때 성능도 향상시켰습니다.


우리 프로젝트의 각 기능이나 새로운 기술 솔루션은 "플래그"로 출시됩니다. 이 플래그는 플레이어의 프로필에 저장되며 게임이 시작될 때 잔액과 함께 클라이언트에 전달됩니다. 일반적으로 새로운 기능, 특히 기술적인 기능이 출시되면 여러 클라이언트 릴리스에 이전 기능과 새로운 기능이 모두 포함됩니다. 새로운 기능 활성화는 위에서 설명한 플래그 상태에 따라 엄격하게 발생하므로 특정 솔루션의 기술적 성공을 실시간으로 모니터링하고 조정할 수 있습니다.


점차적으로 프로젝트의 종속성 주입 기능을 업데이트할 때가 되었습니다. 현재 버전은 더 이상 많은 수의 종속성에 대처할 수 없으며 어떤 경우에는 끊고 리팩토링하기 매우 어려운 불분명한 연결이 도입되었습니다. (이는 UI와 관련된 혁신의 경우 특히 그렇습니다.)


새로운 솔루션을 선택할 때 선택은 간단했습니다. 다른 프로젝트에서 입증된 잘 알려진 Zenject였습니다. 이 프로젝트는 오랫동안 개발되어 적극적으로 지원되고 새로운 기능이 추가되고 있으며 팀의 많은 개발자가 어떤 방식으로든 익숙했습니다.


조금씩 Zenject를 사용하여 War Robot을 다시 작성하기 시작했습니다. 모든 새로운 모듈은 이를 통해 개발되었으며 이전 모듈은 점차적으로 리팩터링되었습니다. Zenject를 사용한 이후로 앞서 논의한 컨텍스트(전투 및 격납고) 내에서 보다 명확한 로딩 서비스 순서를 얻었으며 이를 통해 개발자는 프로젝트 개발에 더욱 쉽게 뛰어들 수 있을 뿐만 아니라 보다 자신 있게 새로운 기능을 개발할 수 있었습니다. 이러한 맥락에서.


비교적 새로운 버전의 Unity에서는 async/await를 통해 비동기 코드로 작업하는 것이 가능해졌습니다. 우리 코드는 이미 비동기 코드를 사용했지만 코드베이스 전체에 단일 표준이 없었고 Unity 스크립팅 백엔드가 async/await를 지원하기 시작한 이후로 우리는 R&D를 수행하고 비동기 코드에 대한 접근 방식을 표준화하기로 결정했습니다.


또 다른 동기는 코드에서 콜백 지옥을 제거하는 것이었습니다. 이는 순차적인 비동기 호출 체인이 있고 각 호출이 다음 호출의 결과를 기다리는 경우입니다.


당시에는 RSG나 UniRx와 같은 몇 가지 인기 있는 솔루션이 있었습니다. 우리는 그것들을 모두 비교하여 단일 테이블로 컴파일했습니다.



RSG. 약속

TPL

대기가 있는 TPL

유니태스크

비동기식 UniTask

완료까지 남은 시간, 초

0.15843

0.1305305

0.1165172

0.1330536

0,1208553

첫 번째 프레임 시간/자체, ms

105.25/82.63

13.51/11.86

21.89/18.40

28.80/24.89

19.27/15.94

첫 번째 프레임 할당

40.8MB

2.1MB

5.0MB

8.5MB

5.4MB

두 번째 프레임 시간/자체, ms

55.39/23.48

0.38/0.04

0.28/0.02

0.32/0.03

0.69/0.01

두 번째 프레임 할당

3.1MB

10.2KB

10.3KB

10.3KB

10.4KB


궁극적으로 우리는 대부분의 개발자에게 익숙한 비동기 C# 코드 작업을 위한 표준으로 기본 async/await를 사용하기로 결정했습니다. 우리는 UniRx.Async를 사용하지 않기로 결정했습니다. 왜냐하면 플러그인의 장점이 타사 솔루션에 의존할 필요성을 커버하지 못했기 때문입니다.


우리는 최소한의 필수 기능을 따르는 경로를 선택했습니다. 우리는 RSG.Promise 또는 홀더의 사용을 포기했습니다. 우선 일반적으로 익숙하지 않은 이러한 도구를 사용하여 작업할 수 있도록 새로운 개발자를 교육해야 했고, 두 번째로 이를 수행하는 타사 코드에 대한 래퍼를 만들어야 했기 때문입니다. RSG.Promise 또는 홀더에서 비동기 작업을 사용합니다. async/await의 선택은 회사 프로젝트 간의 개발 접근 방식을 표준화하는 데도 도움이 되었습니다. 이러한 전환으로 문제가 해결되었습니다. 결국 비동기 코드 작업을 위한 명확한 프로세스가 마련되었고 프로젝트에서 지원하기 어려운 콜백 지옥이 제거되었습니다.


UI가 점차 개선되었습니다. 우리 팀에서는 새로운 기능의 기능은 클라이언트 프로그래머가 개발하고 레이아웃 및 인터페이스 개발은 UI/UX 부서에서 수행하므로 동일한 기능에 대한 작업을 병렬화할 수 있는 솔루션이 필요했습니다. 프로그래머가 로직을 작성하는 동안 레이아웃 디자이너는 인터페이스를 생성하고 테스트할 수 있습니다.


이 문제에 대한 해결책은 인터페이스 작업의 MVVM 모델로 전환하는 과정에서 발견되었습니다. 이 모델을 통해 인터페이스 디자이너는 프로그래머의 개입 없이 인터페이스를 설계할 수 있을 뿐만 아니라 실제 데이터가 아직 연결되지 않았을 때 인터페이스가 특정 데이터에 어떻게 반응하는지 확인할 수 있습니다. 기성 솔루션에 대한 몇 가지 연구와 Pixonic ReactiveBindings라는 자체 솔루션의 신속한 프로토타이핑을 거쳐 우리는 다음 결과를 포함하는 비교표를 작성했습니다.



CPU 시간

기억. 할당

기억. 용법

페퍼민트 데이터 바인딩

367ms

73KB

17.5MB

디스플레이팹

223ms

147KB

8.5MB

유니티 용접

267ms

90KB

15.5MB

Pixonic ReactiveBindings

152ms

23KB

3MB


주로 새로운 인터페이스의 생성을 단순화한다는 측면에서 새로운 시스템이 입증되자마자 우리는 프로젝트에 나타나는 모든 새로운 기능뿐만 아니라 모든 새로운 프로젝트에 이 시스템을 사용하기 시작했습니다.


차세대 모바일 장치를 위한 게임 리마스터

2019년까지 그래픽 측면에서 상당히 강력한 Apple과 Samsung의 여러 장치가 출시되었으므로 우리 회사는 War Robots를 대폭 업그레이드하겠다는 아이디어를 내놓았습니다. 우리는 이 모든 새로운 장치의 성능을 활용하고 게임의 시각적 이미지를 업데이트하고 싶었습니다.


업데이트된 이미지 외에도 업데이트된 제품에 대한 몇 가지 요구 사항도 있었습니다. 즉, 60FPS 게임 모드를 지원하고 다양한 장치에 대한 다양한 리소스 품질을 지원하고 싶었습니다.


현재 품질 관리자는 또한 블록 내의 품질 수가 증가함에 따라 재작업이 필요했습니다. 즉석에서 전환되어 생산성이 저하되고 각각 테스트해야 하는 엄청난 수의 순열이 생성되어 추가 부담이 발생했습니다. 각 릴리스마다 QA 팀의 비용이 발생합니다.


클라이언트를 재작업할 때 가장 먼저 시작한 일은 촬영 리팩토링이었습니다. 원래 구현은 게임 엔터티와 클라이언트의 시각적 표현이 하나의 동일한 개체였기 때문에 프레임 렌더링 속도에 따라 달라졌습니다. 우리는 샷의 게임 엔터티가 더 이상 시각적 요소에 의존하지 않도록 이러한 엔터티를 분리하기로 결정했으며, 이를 통해 프레임 속도가 다른 장치 간에 더 공정한 플레이가 가능해졌습니다.


게임은 많은 수의 사격을 다루지만 이들의 데이터를 처리하는 알고리즘은 이동, 적의 공격 여부 결정 등 매우 간단합니다. 엔터티 구성 요소 시스템 개념은 발사체 이동 논리를 구성하는 데 완벽하게 들어맞았습니다. 그래서 우리는 그것을 고수하기로 결정했습니다.


또한 모든 새 프로젝트에서 이미 ECS를 사용하여 로직 작업을 수행하고 있었으며, 통합을 위한 주요 프로젝트에 이 패러다임을 적용해야 할 때였습니다. 작업을 완료한 결과, 우리는 60FPS에서 이미지를 실행할 수 있는 능력을 보장하는 핵심 요구 사항을 깨달았습니다. 그러나 모든 전투 코드가 ECS로 이전되지 않았기 때문에 이 접근 방식의 잠재력을 완전히 실현할 수는 없었습니다. 궁극적으로 우리는 원하는 만큼 성능을 향상시키지는 못했지만 성능을 저하시키지도 않았습니다. 이는 여전히 강력한 패러다임과 아키텍처 변화에 대한 중요한 지표입니다.


동시에 우리는 새로운 그래픽 스택으로 어떤 수준의 그래픽을 달성할 수 있는지 확인하기 위해 PC 버전 작업을 시작했습니다. 당시에는 아직 프리뷰 버전이었고 끊임없이 변화하고 있던 Unity SRP를 활용하기 시작했습니다. Steam 버전에 나온 사진은 매우 인상적이었습니다.



또한 위 이미지에 표시된 그래픽 기능 중 일부는 강력한 모바일 장치로 전송될 수 있습니다. 이는 특히 역사적으로 좋은 성능 특성, 뛰어난 드라이버, 하드웨어와 소프트웨어의 긴밀한 조합을 갖춘 Apple 장치의 경우였습니다. 이를 통해 그들은 우리 측의 임시 솔루션 없이도 매우 높은 품질의 사진을 생성할 수 있습니다.


우리는 그래픽 스택을 변경하는 것만으로는 이미지가 변경되지 않는다는 것을 빨리 이해했습니다. 또한 강력한 장치 외에도 약한 장치를 위한 콘텐츠가 필요하다는 사실도 분명해졌습니다. 그래서 우리는 다양한 품질 수준에 맞는 콘텐츠를 개발할 계획을 시작했습니다.


이는 기계, 총, 맵, 효과 및 해당 텍스처가 품질면에서 분리되어야 함을 의미하며, 이는 품질에 따라 다른 개체로 변환됩니다. 즉, HD 품질에서 작동하는 물리적 모델, 텍스처 및 기계 텍스처 세트는 다른 품질에서 작동하는 기계와 다릅니다.


게다가, 게임은 지도에 많은 양의 자원을 투자하고 있으며, 지도 역시 새로운 품질에 맞게 리메이크되어야 합니다. 또한 현재의 품질 관리자가 자산 품질을 관리하지 않아 우리의 요구를 충족시키지 못하는 것이 분명해졌습니다.


그래서 먼저 우리 게임에서 어떤 특성을 사용할 수 있는지 결정해야 했습니다. 현재 품질 관리자의 경험을 고려하여 우리는 새 버전에서 특정 장치에 사용 가능한 최대 품질에 따라 사용자가 설정에서 독립적으로 전환할 수 있는 몇 가지 고정된 품질을 원한다는 것을 깨달았습니다.


새로운 품질 시스템은 사용자가 소유한 장치를 결정하고 장치 모델(iOS의 경우)과 GPU 모델(Android의 경우)을 기반으로 특정 플레이어에 대해 사용 가능한 최대 품질을 설정할 수 있습니다. 이 경우 이 품질은 물론 이전의 모든 품질도 사용할 수 있습니다.


그리고 각 화질별로 최대 FPS를 30~60으로 전환하는 설정이 있습니다. 당초에는 5가지 정도(ULD, LD, MD, HD, UHD) 정도의 화질을 가질 계획이었습니다. 그러나 개발 과정에서 이러한 수준의 품질을 개발하는 데 매우 오랜 시간이 걸리고 QA에 대한 부담을 줄일 수 없다는 것이 분명해졌습니다. 이를 염두에 두고 궁극적으로 게임의 품질은 HD, LD, ULD로 결정되었습니다. (참고로 현재 이러한 퀄리티를 가지고 플레이하는 관객의 분포는 HD - 7%, LD - 72%, ULD - 21% 입니다.)


우리는 더 많은 품질을 구현해야 한다는 것을 이해하자마자 해당 품질에 따라 자산을 정렬하는 방법을 연구하기 시작했습니다. 이 작업을 단순화하기 위해 우리는 다음 알고리즘에 동의했습니다. 아티스트는 최대 품질(HD) 자산을 만든 다음 스크립트 및 기타 자동화 도구를 사용하여 이러한 자산의 일부를 단순화하고 다른 품질의 자산으로 사용합니다.


이 자동화 시스템을 작업하는 과정에서 우리는 다음과 같은 솔루션을 개발했습니다.

  • Asset Importer – 텍스처에 필요한 설정을 지정할 수 있습니다.
  • Mech Creator – Unity Prefab 변형을 기반으로 여러 기계 버전을 생성하고 품질 및 텍스처 설정을 해당 프로젝트 폴더에 배포할 수 있는 도구입니다.
  • Texture Array Packer – 텍스처를 텍스처 배열로 압축할 수 있는 도구
  • Quality Map Creator – 소스 UHD 품질 지도에서 다양한 지도 품질을 생성하기 위한 도구


기존 기계 및 지도 리소스를 리팩터링하기 위해 많은 작업이 수행되었습니다. 원래 기계는 다양한 품질을 염두에 두고 설계되지 않았으므로 단일 조립식 건물에 저장되었습니다. 리팩토링 후 주로 로직을 포함하는 기본 부분이 추출되었으며 Prefab Variants를 사용하여 특정 품질에 대한 텍스처가 있는 변형이 생성되었습니다. 또한 품질에 따른 텍스처 저장 폴더의 계층 구조를 고려하여 기계를 다양한 품질로 자동으로 나눌 수 있는 도구를 추가했습니다.


특정 자산을 특정 디바이스에 전달하기 위해서는 게임 내 모든 콘텐츠를 번들과 팩으로 나누어야 했습니다. 메인 팩에는 게임을 실행하는 데 필요한 자산, 모든 용량에 사용되는 자산은 물론 Android_LD, Android_HD, Android_ULD, iOS_LD, iOS_HD, iOS_ULD 등 각 플랫폼별 품질 팩이 포함되어 있습니다.


우리 플랫폼 팀이 만든 ResourceSystem 도구 덕분에 자산을 팩으로 나누는 것이 가능해졌습니다. 이 시스템을 통해 우리는 자산을 별도의 패키지로 수집한 다음 이를 클라이언트에 포함하거나 별도로 가져와 CDN과 같은 외부 리소스에 업로드할 수 있었습니다.


콘텐츠를 전달하기 위해 우리는 역시 플랫폼 팀에서 만든 DeliverySystem이라는 새로운 시스템을 사용했습니다. 이 시스템을 사용하면 ResourceSystem에서 생성된 매니페스트를 수신하고 지정된 소스에서 리소스를 다운로드할 수 있습니다. 이 소스는 모놀리식 빌드, 개별 APK 파일 또는 원격 CDN일 수 있습니다.


처음에는 리소스팩 저장을 위해 Google Play(Play Asset Delivery)와 AppStore(On-Demand Resources)의 기능을 사용할 계획이었지만, Android 플랫폼에서는 자동 클라이언트 업데이트와 관련된 문제가 많았으며, 저장된 리소스의 수


또한 내부 테스트 결과 CDN을 사용하는 콘텐츠 전달 시스템이 가장 잘 작동하고 가장 안정적인 것으로 나타났습니다. 그래서 우리는 매장에 리소스를 저장하는 것을 포기하고 클라우드에 저장하기 시작했습니다.


리마스터 출시

리마스터에 대한 주요 작업이 완료되자 출시 시기가 다가왔습니다. 그러나 우리는 사용자가 5~10GB의 데이터를 다운로드해야 하는 시중에 나와 있는 많은 인기 게임에도 불구하고 원래 계획된 3GB 크기가 열악한 다운로드 경험이라는 것을 빨리 이해했습니다. 우리의 이론은 우리가 리마스터링한 게임을 시장에 출시할 때쯤이면 사용자들이 이 새로운 현실에 익숙해질 것이라는 것이었지만 아쉽습니다.


즉, 플레이어는 모바일 게임에서 이러한 대용량 파일에 익숙하지 않았습니다. 우리는 이 문제에 대한 해결책을 빨리 찾아야 했습니다. 우리는 이후 여러 차례 HD 품질이 포함되지 않은 버전을 출시하기로 결정했지만 나중에 사용자에게 제공했습니다.


왼쪽 – 리마스터 이전, 오른쪽 – 이후


리마스터 개발과 병행하여 우리는 프로젝트 테스트를 자동화하기 위해 적극적으로 노력했습니다. QA 팀은 프로젝트 상태를 자동으로 추적할 수 있도록 훌륭한 작업을 수행했습니다. 현재 우리는 게임이 실행되는 가상 머신을 갖춘 서버를 보유하고 있습니다. 자체 작성 테스트 프레임워크를 사용하면 스크립트가 포함된 프로젝트의 아무 버튼이나 누를 수 있으며, 장치에서 직접 테스트할 때 동일한 스크립트를 사용하여 다양한 시나리오를 실행합니다.


우리는 이 시스템을 계속 개발하고 있습니다. 안정성, 성능 및 올바른 논리 실행을 확인하기 위해 이미 수백 개의 지속적으로 실행되는 테스트가 작성되었습니다. 결과는 개발자와 함께 QA 전문가가 가장 문제가 있는 영역(테스트 실행의 실제 스크린샷 포함)을 자세히 검사할 수 있는 특수 대시보드에 표시됩니다.


현 시스템을 가동하기 전 회귀 테스트에 많은 시간이 소요됐고(기존 프로젝트 기준 약 1주일), 내용량이나 내용 면에서도 현 시스템보다 훨씬 적었다. 그러나 자동 테스트 덕분에 현재 버전의 게임은 이틀 동안만 테스트됩니다. 이는 더 개선될 수 있지만 현재는 시스템에 연결된 장치 수에 의해 제한됩니다.


리마스터가 완료될 무렵, Apple 팀은 당사에 연락하여 새로운 Apple A14 Bionic 칩(2020년 가을에 새로운 iPad와 함께 출시됨)의 기능을 시연하기 위해 신제품 프레젠테이션에 참여할 기회를 주었습니다. 새로운 그래픽. 이 미니 프로젝트를 진행하는 동안 Apple 칩에서 120FPS로 실행할 수 있는 완벽하게 작동하는 HD 버전이 생성되었습니다. 또한 새로운 칩의 성능을 보여주기 위해 몇 가지 그래픽 개선 사항이 추가되었습니다.


경쟁적이고 다소 어려운 선택의 결과로 우리 게임은 Apple 이벤트의 가을 프레젠테이션에 포함되었습니다! 팀 전체가 모여서 이 이벤트를 보고 축하했는데, 정말 멋졌습니다!



Photon을 포기하고 WorldState 아키텍처로 마이그레이션합니다.

2021년 리마스터 버전 게임 출시를 앞두고도 새로운 과제가 등장했다. 많은 사용자들이 네트워크 문제에 대해 불만을 토로했는데, 그 근본 원인은 당시 우리의 현재 솔루션인 Photon Server SDK와 함께 작동하는 데 사용된 Photon 전송 계층이었습니다. 또 다른 문제는 무작위 순서로 서버에 전송되는 표준화되지 않은 대량의 RPC가 존재한다는 것입니다.


또한, 월드 동기화 문제와 경기 시작 시 메시지 대기열 오버플로로 인해 상당한 지연이 발생할 수 있는 문제도 있었습니다.


상황을 해결하기 위해 우리는 RPC 호출이 아닌 패킷과 게임 상태 수신을 통해 서버와의 통신이 이루어지는 보다 일반적인 모델로 네트워크 매치 스택을 이동하기로 결정했습니다.


새로운 온라인 매치 아키텍처는 WorldState라고 불리며 게임 플레이에서 Photon을 제거하기 위한 것이었습니다.

LightNetLib 라이브러리를 기반으로 Photon에서 UDP로 전송 프로토콜을 바꾸는 것 외에도 이 새로운 아키텍처에는 클라이언트-서버 통신 시스템을 간소화하는 작업도 포함되었습니다.


이 기능에 대한 작업의 결과로 우리는 서버 측 비용을 절감했고(Windows에서 Linux로 전환하고 Photon Server SDK 라이센스 포기) 사용자 최종 장치에 훨씬 덜 요구되는 프로토콜을 사용하여 문제의 수를 줄였습니다. 서버와 클라이언트 간의 상태 비동기화를 통해 새로운 PvE 콘텐츠를 개발할 수 있는 기회를 만들었습니다.


전체 게임 코드를 하룻밤 사이에 변경하는 것은 불가능했기 때문에 WorldState 작업은 여러 단계로 나누어졌습니다.


첫 번째 단계는 클라이언트와 서버 간의 통신 프로토콜을 완전히 재설계하는 것이었고 기계의 움직임이 새로운 레일로 전환되었습니다. 이를 통해 우리는 게임의 새로운 모드인 PvE를 만들 수 있었습니다. 점차적으로 기계공, 특히 최신 기계공(기계에 대한 손상 및 치명적인 손상)이 서버로 이동하기 시작했습니다. 기존 코드를 WorldState 메커니즘으로 점진적으로 이전하는 작업이 계속되고 있으며 올해에도 몇 가지 업데이트가 있을 예정입니다.


2022년에 우리는 새로운 플랫폼인 Facebook Cloud를 출시했습니다. 플랫폼 뒤에 있는 개념은 흥미로웠습니다. 최종 플레이어가 게임을 실행하기 위해 강력한 PC나 스마트폰을 가질 필요 없이 클라우드의 에뮬레이터에서 게임을 실행하고 스마트폰과 PC의 브라우저로 스트리밍하는 것입니다. 안정적인 인터넷 연결만 필요합니다.


개발자 측에서는 플랫폼이 사용할 기본 빌드로 Android 빌드와 Windows 빌드라는 두 가지 유형의 빌드를 배포할 수 있습니다. 우리는 이 플랫폼에 대한 더 많은 경험을 바탕으로 첫 번째 길을 택했습니다.


Facebook 클라우드에서 게임을 출시하려면 게임에서 인증을 다시 실행하고 커서 제어를 추가하는 등 몇 가지 수정 작업이 필요했습니다. 또한 플랫폼이 CDN을 지원하지 않았기 때문에 모든 내장 리소스가 포함된 빌드를 준비해야 했고, 에뮬레이터에서 항상 올바르게 실행될 수 없는 통합을 구성해야 했습니다.


Facebook 에뮬레이터는 실제 Android 장치가 아니고 드라이버 구현 및 리소스 관리 측면에서 고유한 특성을 가지고 있었기 때문에 그래픽 스택의 기능을 보장하기 위해 그래픽 측면에서도 많은 작업이 수행되었습니다.


그러나 우리는 이 플랫폼의 사용자가 불안정한 연결과 에뮬레이터의 불안정한 작동 등 많은 문제에 직면한 것을 확인했으며 Facebook은 2024년 초에 플랫폼을 폐쇄하기로 결정했습니다.




프로그래머 측에서 끊임없이 발생하고 짧은 기사에서 자세히 논의할 수 없는 일은 프로젝트의 기술적 위험에 대한 정기적인 작업, 기술 지표의 정기적인 모니터링, 메모리 및 리소스 최적화에 대한 지속적인 작업, 문제 검색입니다. 파트너 SDK, 광고 통합 등의 타사 솔루션.


또한 심각한 충돌 및 ANR을 해결하기 위한 연구와 실무 작업을 계속하고 있습니다. 프로젝트가 완전히 다른 수많은 장치에서 실행될 때 이는 불가피합니다.


이와 별도로 문제의 원인을 찾기 위해 노력하는 사람들의 전문성에 주목하고 싶습니다. 이러한 기술적 문제는 본질적으로 복잡한 경우가 많으며 원인을 찾기 전에 여러 분석 시스템의 데이터를 서로 중첩하고 몇 가지 중요한 실험을 수행해야 합니다. 대부분의 복잡한 문제에는 테스트할 수 있는 일관되게 재현 가능한 사례가 없기 때문에 경험적 데이터와 전문적인 경험을 사용하여 문제를 해결하는 경우가 많습니다.


프로젝트에서 문제를 찾는 데 사용하는 도구와 리소스에 대해 몇 마디 언급해야 합니다.


  • AppMetr – 장치에서 익명화된 데이터를 수집하여 플레이어 문제를 연구할 수 있는 내부 분석 솔루션입니다. 독자에게 더 잘 알려져 있을 수 있는 유사한 도구로는 Firebase Analytics, Google Analytics, Flurry, GameAnalytics, devtodev, AppsFlyer 등이 있습니다.
  • Google Firebase Crashlytics
  • Google Play Console – Android Vitals
  • 로그 – 디버그 빌드의 로그 시스템으로, 스튜디오 내 플레이 테스트에서 문제 검색을 최소화할 수 있습니다.
  • 공개 테스트 영역 – 저희 게임에는 새로운 변경 사항을 테스트하고 다양한 기술 실험을 수행할 수 있는 공개 테스트 서버가 있습니다.
  • 유니티 프로파일러
  • XCode 도구


이것은 프로젝트가 존재하는 동안 겪은 기술적 개선의 작은 목록일 뿐입니다. 프로젝트가 지속적으로 개발되고 있기 때문에 성취된 모든 것을 나열하기는 어렵습니다. 기술 관리자는 최종 사용자와 스튜디오 내부에서 제품을 사용하는 사람들 모두를 위해 제품 성능을 향상시키기 위한 계획을 작성하고 구현하기 위해 끊임없이 노력하고 있습니다. 개발자 자신과 다른 부서.


우리는 향후 10년 동안 제품에 대한 많은 개선 사항을 갖고 있으며 다음 기사에서 이러한 내용을 공유할 수 있기를 바랍니다.


War Robots님, 생일을 축하합니다. 이 모든 것을 가능하게 해준 거대한 기술 전문가 팀에게 감사드립니다!