
# LEGO Horizon Adventures Nintendo Switch 테마 최적화 여정
## 소개
* **발표자:** Giang (CoreTech 팀 엔지니어, Studio GoBo)
* **주요 내용:** LEGO Horizon Adventures 게임의 테마를 Nintendo Switch 플랫폼에서 최적화한 과정 공유
* **발표 방식:** 일반적인 성공 사례 발표가 아닌, 특정 문제 해결을 위한 반복적인 시도와 실패, 발견에 초점
---
## 게임 개요
* **개발사:** Studio GoBo (영국 브라이튼 기반, 원격 근무자 다수)
* **게임:** LEGO Horizon Adventures
* **플랫폼:** PC, PS5, Nintendo Switch (Unreal Engine 5.3 사용)
* **특징:**
* 레고 브릭으로 완전히 구축된 세계
* 시네마틱 표준의 실시간 렌더링 추구
* 미니어처화되고 사실적인 브릭 월드 구현 목표
---
## 테마 구축 초기 접근 방식
* **기존 레고 게임과 차별화:** 일반적인 게임 환경에 레고 미니피겨를 배치하는 방식 지양
* **핵심 목표:** "레고 브릭 형태의 Horizon 테마" 구현
* **초기 아이디어:**
* *수작업으로 만든 독특한 테마 모델:* 제작에 막대한 시간 소요 및 게임플레이 카메라에서 노이즈 발생 문제로 기각
* **선택한 접근 방식:** 모듈식 타일 활용
* 크기와 각도에 대한 엄격한 규칙으로 타일 결합
* *개별 타일 수동 배치:* 매우 지루하고 힘든 작업
---
## 테마 도구 개발
* **목표:** 타일 배치 과정 자동화 및 효율 증대
* **기능:**
* 페인팅 스타일의 상호 작용 지원
* 다양한 타일 타입 및 바이옴별 타일셋 적용
* 실시간 피드백을 통한 빠른 실험 및 탐색 지원
* **기술적 구현:**
* 도구 출력: 각 타일 모서리의 좌표, 높이, 타입을 포함하는 그리드 데이터
* 데이터 저장: "테마 패치" 액터
* 최종 테마 생성: 타일 데이터와 타일셋을 활용
---
## 테마 타일 및 타일셋
* **타일셋:** 각 높이 조합에 사용할 메쉬 구성 포함
* **반복 방지:** 각 타일 타입별 다양한 변형 존재
* **타일 예시:**
* 세 개의 모서리가 길(path)이고 하나는 땅(ground)인 타일 -> 해당 형태의 타일 사용
* 경사면을 표현하기 위한 슬로프 메쉬 적용
* **바이옴별 타일셋:**
* 다양한 바이옴에 맞는 시각적 테마 적용 가능
* 테마 패치 재테마화 용이
---
## 렌더링 파이프라인
* **메쉬 파이프라인:** 모든 게임 내 지오메트리와 동일한 파이프라인 사용
* **Houdini 활용:** 절차적 메쉬 생성 (동료 Simon 발표 참고)
* **레고 모델링 소프트웨어:** 최적화된 메쉬 생성
* **플랫폼별 LOD:**
* **하이엔드 플랫폼:** Nanite, Lumen 활용 (LOD 0)
* **Switch:** 전통적인 렌더링 방식 (LOD 1부터 시작), 다수의 드로우 콜 발생
* **Switch 렌더링 특징:**
* *레고 스터드:* 지오메트리가 아닌, 카메라에 보이는 빌보드에 레이 트레이싱하여 렌더링 (단일 드로우 콜)
---
## 색상 변경 도구 (Recoloring Tool)
* **기능:** 테마 패치 위에 사용자 지정 색상 적용
* **지원 방식:** 브러시 스타일, 버킷 스타일 페인팅
* **색상 프리셋 저장:** 재사용 가능
* **장점:**
* 모델 에셋을 복제하지 않고 시각적 다양성 확보
* 테마 모델뿐 아니라 모든 레고 모델에 적용 가능
---
## 테마 시각적 다양성 확보 도구
* **바이옴별 타일셋:** 특정 바이옴에 시각적 아이덴티티 부여 (색상 팔레트, 브릭 모양 활용)
* *숲/노라 지역:* 부드럽고 둥근 브릭 타일 (친근한 느낌)
* *사막/정글:* 각진 모양의 브릭 타일
* **레벨별 색상 페인팅:** 타일 모델 및 타일셋 관리 부담 없이 색상 변경 가능
---
## Switch 플랫폼 최적화 문제: 높은 드로우 콜 수
* **문제점:** Switch에서 개별 테마 패치로 인해 발생하는 높은 드로우 콜 수 (최대 1,000개)
* **성능 대시보드:** 렌더 스레드 시간과 드로우 콜 수의 상관관계 확인
* **목표:** 렌더 스레드 부담 완화를 위해 드로우 콜 수 2,500개 이하 유지
* **제약 조건:**
* 기존 아티스트 워크플로우 변경 최소화
* 이미 완성 단계에 있는 다수의 레벨 수정 불가
---
## 최적화 시도 1: 인스턴싱 (Instancing)
* **아이디어:** 개별 로컬 인스턴스 타일을 Hierarchical Instanced Static Mesh Component (HISMC)로 통합
* **결과:**
* **CPU:** HISMC 관련 렌더 스레드 비용 증가 (뷰 가시성, 동적 그림자 등)
* **GPU:** 높은 프리미티브 카운트로 인한 성능 저하
* **결론:** 기대 이하의 성능, 사용 불가 (엔진 버전 업데이트에 따라 개선 가능성 있음)
---
## 최적화 시도 2: 개별 테마 패치 메쉬 생성
* **아이디어:** 각 테마 패치를 고유한 레고 모델로 생성
* **문제점:**
* 복잡한 데이터 변환 과정, 비효율적
* **엄청난 애셋 수 증가:** 수백 개의 레벨 x 수십 개의 패치 = 수천 개의 모델 생성
* 기존 애셋 용량 (800MB) 대비 심각한 용량 증가 우려
---
## 최적화 시도 3: 프록시 메쉬 (Proxy Mesh)
* **아이디어:** 멀리 있는 테마 패치를 병합되고 단순화된 버전으로 교체 (Unreal Engine의 H-Law 시스템과 유사)
* **핵심 구성 요소:**
1. **메쉬 병합:**
* `Dynamic Mesh` 활용: 유연성이 높고 외부 프로세스 불필요
* 개별 타일 메쉬를 `Dynamic Mesh`로 복사 후 병합하여 새 Static Mesh 애셋 생성
* *적용:* 높은 LOD 메쉬를 사용하여 폴리 카운트 감소
2. **런타임 표시:**
* 단순 알고리즘 기반: 테마 패치의 바운딩 박스 크기 및 깊이 값으로 원거리 판단
* *프록시 모드:* 화면 밖 또는 원거리/작은 패치는 병합된 메쉬 표시, 나머지는 개별 타일 표시
* **결과:**
* 드로우 스레드 비용 획기적 감소 (0.5 ~ 2.5ms)
* GPU 시간 및 트라이앵글 수 증가 (추가 개선 필요)
---
## 프록시 메쉬 개선
* **패치 분할:** 큰 패치의 일부만 보이는 경우, 낭비되는 데이터 전송 방지 위해 작은 청크로 분할
* 폴리 카운트 및 GPU 시간 감소
* **애셋 관리:**
* 변경 사항 자동 감지 및 재생성 (체크섬 활용)
* 야간 빌드 작업으로 자동 업데이트
* **애셋 크기 최적화:**
* 하이 LOD 메쉬 사용
* 사용되지 않는 UV 채널 제거
* 레이 트레이싱 가속 구조 제거
* 내비게이션 및 충돌 정보 제거 (기존 타일은 숨겨진 상태로 유지)
* 메쉬 거리 필드 제거
* *결과:* 애셋 크기 90% 감소 (예: Hub 레벨 100MB -> 8MB)
---
## 색상 변경 기능 통합
* **문제점:** 프록시 메쉬에서의 색상 변경 정확도 문제
* **기존 색상 변경 방식:**
* Houdini 파이프라인: UV 채널 1 (색상 ID), UV 채널 2 (브릭 ID) 사용
* 씬 프록시: 룩업 버퍼를 통해 색상 지정
* **프록시 메쉬 적용:**
* 동적 룩업 제거, 모든 색상 정보를 UV1에 직접 기록
* 기존 머티리얼 재사용
* UV2 제거로 메모리 및 패키지 크기 감소
* **구현:** `Dynamic Mesh`의 `Edit Mesh` 함수를 사용하여 UV1에 색상 값 기록
---
## 동적 드로우 거리 (Dynamic Draw Distance)
* **목표:** 고정된 깊이 오브 필드(DOF) 거리를 상황에 따라 동적으로 조절
* **영향 요소:** 협동 모드 플레이어, 맵의 흥미로운 지점, 전투 중 엔티티 등
* **구현:**
* 씬 카메라 컴포넌트 정보 활용
* DOF 포스트 프로세스 셰이더 공식 수정
* 버퍼 거리 추가하여 눈에 띄는 팝핑 현상 방지
---
## 런타임 코드 최적화: 'End of Frame' 히치 현상
* **원인:** 복잡한 지역에서 많은 정적 메쉬 컴포넌트의 가시성 변경 시 발생하는 히치
* **문제:** `SetVisibility` 호출이 렌더 스레드에서 처리될 때, 프록시 할당/설정 비용 발생
* **시도:**
* *Staggered Update:* 프레임당 가시성 변경 컴포넌트 수 제한
* *Custom Visibility Pass:* 씬 뷰의 프리미티브 가시성 맵 활용
* 결과: 히치 현상 완화되었으나, 기본 비용 증가 및 런타임 메모리 사용량 증가
---
## 최종 결과 및 교훈
* **성능 목표 달성:** 품질 손실 최소화, 아티스트도 시각적 팝핑 인지 불가
* **애셋 크기 증가:** 약간의 추가 메가바이트 발생 (허용 범위 내)
* **자동화:** 대부분 자동화되어 아티스트 부담 최소화
* **교훈:**
* **반복과 분석:** 최적화 과정에서 반복적인 실험과 분석이 중요
* **작고 간단한 솔루션의 조합:** 복잡한 문제도 여러 단순한 해결책으로 해결 가능
* **팀워크:** 최적화는 여러 분야의 협업을 통해 이루어지는 팀 노력
* **명명 규칙:** 충돌 방지를 위해 `primitive`, `proxy`와 같은 일반적인 이름 피하기
---
## 추가 정보
* 동료들의 발표 자료 및 QR 코드 제공
* 발표 슬라이드 온라인 공개 예정
* LinkedIn 통한 추가 문의 가능