안녕하세요, 저는 오션혼 2: 나이츠 오브 더 로스트 렐름(Oceanhorn 2: Knights of the Lost Realm)의 시니어 그래픽 프로그래머인 칼레 하말라이넨(Kalle Hämäläinen)입니다. 이 블로그 포스트에서는 애플 아케이드(Apple Arcade)를 지원하는 모든 기기(iPhone 6s에서 최신 MacBook Pro까지)용으로 개발한 게임을 어떻게 닌텐도 스위치(Nintendo Switch)로 포팅했는지 설명하겠습니다.
우리는 다음과 같은 목표를 세웠습니다.
가능한 한 최고의 퀄리티를 유지합니다.
안정적인 프레임 레이트를 구현합니다.
네이티브 해상도(도킹 모드 1080p, 휴대 모드 720p)를 확보합니다.
MSAA(iOS에서 사용) 또는 템포럴 AA(Mac에서 사용) 대신 다이내믹 해상도를 통해 슈퍼샘플링한 안티 에일리어싱을 사용합니다.
렌더링 기능보다는 해상도를 우선으로 하여 PC 렌더러 대신 모바일 렌더러를 사용합니다.
우리는 엔진 소프트웨어(Engine Software) 스튜디오와 협업해 스위치 포팅 작업을 진행했습니다. 상대적으로 클럭 속도가 느린 CPU 코어 세 개를 사용하는 스위치 하드웨어로는 우리 목표를 이루는 데 무리가 있었습니다.
첫 이터레이션 작업
첫 번째 스위치 포팅 이터레이션 작업에서는 속도가 고작 13fps가 나왔습니다. iOS에서는 개발 당시 목표가 30fps였습니다. 애플 아케이드가 처음 발표되었을 때는 어떤 기기를 최소 사양으로 설정할지 확실하지 않았습니다(결국 iPhone 6s로 결정되었습니다). 30fps를 목표로 해야 고해상도를 유지할 수 있었고, 무엇보다 배터리 소모량이 안정적이었습니다.
해결책
30fps인 경우, 프레임당 33.3밀리초의 렌더링 시간이 주어지는데, 안타깝게도 첫 테스트에서는 프레임당 거의 80밀리초가 소요되었습니다. 우리는 당황했습니다. 게임이 이미 모바일 기기용으로 최적화되어 있었는데 말이죠. 우리가 뭘 놓쳤던 걸까요? 알고 보니 상당히 많았습니다. 요즘 애플 모바일 기기에는 스위치보다 강력한 CPU가 탑재되어있는 것을 간과해서 리소스를 효율적으로 활용하지 못했던 것입니다. 저는 답을 찾기 위해 게임 프로파일링을 시작했습니다.
콘솔 게임과 모바일 게임은 다릅니다. 모바일에서는 백그라운드 애플리케이션, 배터리 수명, 기기 온도가 퍼포먼스를 좌우합니다. 반면에 콘솔은 안정적인 퍼포먼스를 꾸준히 유지합니다.
저는 속도가 느린 블루프린트를 찾아서 C++로 포팅하는 것으로 최적화 작업을 시작했습니다. 이틀 만에 첫 번째 결과로부터 20밀리초를 절약할 수 있었습니다. 이런 간단한 방법으로 퍼포먼스를 개선하고 나니, 분명히 쉬운 방법이 더 있을 것으로 생각했습니다. 금방 또 다른 방법을 찾았습니다. 일부 레벨은 액터가 권장치보다 훨씬 많은 5천 개 이상이었는데, iOS 기기에서는 별 문제 없이 처리됐지만, 스위치에서는 상당 부분을 변경하지 않고는 처리하기 곤란했습니다.
프레임당 틱이 발생하는 액터의 수를 파악해보니 1,000개가 넘었고, 틱되는 컴포넌트 수도 거의 1,500개였습니다. 그게 문제였습니다. 우선은 프레임당 틱 수를 줄여야 했습니다. 우리가 알아낸 밀리초 절약 방법은 다음과 같습니다.
별다른 행동 없이 업데이트되는 액터는 틱을 아예 비활성화하거나 틱 간격을 현저하게 줄였습니다.
일부 액터는 수동으로 오버랩을 쿼리하고 있었습니다. 이때는 리팩터링을 통해 오버랩 이벤트를 사용하도록 했고, 해당 이벤트 후에 일시적으로만 틱을 활성화했습니다.
순전히 시각적인 활동을 하지만 플레이어에게 보이지 않는액터가 있는데 , 이 경우에는 프러스텀, 거리, 다이내믹 및 스태틱 오클루전 컬링을 사용한 후 보이는 액터만 업데이트했습니다.
화면에 표시되긴 하지만 너무 멀리 있어 알아채기 힘든 액터가 동작하는 경우가 있습니다. 예를 들어, 화이트 시티(White City)에서는 총 300개가 넘는 캐릭터가 항상 존재하지만 플레이어의 주변에 있는 캐릭터는 10여 개 정도에 불과합니다. 즉, 이런 캐릭터만 업데이트하면 되는 것입니다.
언리얼 엔진에는 이러한 경우를 최적화할 방법이 여럿 존재합니다. 하지만 올바른 판단을 내리는 건 팀의 몫이었고, 어떤 경우에는 옵트인 또는 커스텀 코드가 필요합니다. 우리는 포팅 작업 중에 코드를 일부 추가하기도 하고, 제거도 했지만, 애니메이션 틱 레이트와 같은 빌트인 최적화도 사용했습니다.
랜드스케이프 그래스 시스템도 속도 저하의 원인이었습니다. 랜드스케이프 그래스 시스템은 랜드스케이프 위에 수 백만 개의 그래스와 폴리지 메시가 다이내믹하게 스폰되는 시스템인데, 프레임당 최대 2.5밀리초를 사용했던 것으로 드러났습니다. 우리는 각각의 랜드스케이프에 다양한 종류의 폴리지를 사용하는 방식으로 인해 비어있는 배치가 많이 스폰된다는 사실을 알아냈습니다. 이 현상은 컴포넌트의 각 특정 폴리지 타입에 가중치가 0인 경우 조기에 제외하는 것으로 쉽게 수정할 수 있었습니다. 시스템은 랜드스케이프의 모든 컴포넌트도 업데이트하고 있었습니다. 이 점을 수정하기 위해 우선 모든 폴리지 타입의 최대 거리를 살펴본 후, 범위 내에 있는 컴포넌트만 업데이트했습니다. 이에 따라 랜드스케이프 컴포넌트가 4,000개에서 (플레이어 주변의) 10개로 감소하여 렌더 시간이 0.1밀리초로 줄었습니다. 이런 최적화 방식이 프로젝트에 도움이 되겠다고 생각하는 경우 사용하실 수 있도록 GitHub의 언리얼 엔진 최신 버전에 넣어두겠으니, 먼저 GitHub에 로그인하셔서 여기와 여기에서 확인해 보세요.
여러 가지 방법이 더 있지만 마지막으로 말씀드리자면, 엔진 소프트웨어에서는 씨 오브 시브즈(Sea of Thieves)에 사용했던 액터 틱 배칭이라는 기술을 적용했습니다. 액터 틱 배칭을 사용하면 인스트럭션 캐싱 누락을 줄일 뿐만 아니라, 중복 작업을 제거하거나 액터 거리에 기반한 틱 레이트를 최적화하는 등 다른 최적화 가능성을 열어줍니다.
이런 모든 노력을 통해 오션혼 2: 나이츠 오브 더 로스트 렐름을 최적화하여 닌텐도 스위치 버전으로 포팅해 2020년 가을 출시를 앞두고 있습니다. 읽어주셔서 감사합니다!
지금 언리얼 엔진을 다운로드하세요!
세계에서 가장 개방적이고 진보된 창작 툴을 시작하세요.
모든 기능과 무료 소스 코드 액세스를 제공하는 언리얼 엔진은 제작에 바로 사용할 수 있습니다.