메모리 및 CPU 사용량 최적화
에셋 로딩과 객체 수명·Tick·블루프린트 연산의 메모리 및 CPU 비용을 측정해 프레임과 안정성을 개선합니다.
GPU뿐 아니라 메모리와 CPU를 함께 측정하고, 실제 병목인 축부터 조정합니다.
메모리(Memory)와 CPU(Central Processing Unit)는 게임 안정성과 프레임 유지에 직접 연결되는 자원입니다.
메모리가 부족하면 충돌 위험이 커지고, CPU가 과부하되면 프레임 드롭과 입력 지연이 즉시 체감됩니다.
이번 절에서는 언리얼 엔진에서 메모리/CPU 병목을 찾고 조정하는 실전 흐름을 정리합니다.
분석 도구를 바탕으로 병목을 좁혀 나가면, 같은 콘텐츠에서도 훨씬 안정적인 플레이 품질을 만들 수 있습니다.
메모리 및 CPU 사용량 최적화의 중요성
메모리와 CPU 최적화는 사용량이 높은 항목을 찾고, 로딩과 업데이트 비용을 나누어 줄이는 과정입니다.
메모리 및 CPU 최적화는 GPU 최적화만큼이나 게임의 안정성과 성능에 결정적인 영향을 미칩니다.
- 게임 안정성: 메모리 부족(OOM: Out Of Memory)은 게임 충돌을 일으킬 수 있습니다. 메모리 예산과 로딩 중 피크를 관리해 위험을 줄입니다.
- 프레임 속도 (FPS) 유지: CPU는 게임 로직, 물리, AI, 애니메이션 등 다양한 계산을 담당하므로, 프레임의 주요 CPU 작업이 예산을 넘으면 프레임 드롭이 발생할 수 있습니다. 전체 CPU 이용률이 낮아도 한 스레드가 병목일 수 있습니다.
- 로딩 시간 단축: 불필요한 메모리 사용량을 줄이면 게임 로딩 시간을 단축할 수 있습니다.
- 빌드 크기 감소: 사용하지 않거나 중복된 에셋을 제거하여 최종 게임 빌드 크기를 줄일 수 있습니다.
- 멀티태스킹 환경 고려: 게임이 백그라운드에서 실행되거나 다른 앱과 동시에 실행될 때, 메모리 사용량이 적을수록 시스템 전반의 안정성이 높아집니다. (특히 모바일)
메모리 사용량 최적화
메모리(RAM 및 VRAM)는 실행 중 필요한 에셋과 데이터가 상주하는 공간입니다. 모든 에셋이 동시에 로드되는 것은 아닙니다.
효율적인 관리가 필수적입니다.
에셋(Asset) 메모리 최적화
-
텍스처 해상도 및 압축
- 재강조: 9장 2절에서 다룬 텍스처 해상도(Max Texture Size)와 압축 설정(
Compression Settings)은 VRAM 사용량에 가장 큰 영향을 미칩니다. 불필요하게 고해상도 텍스처를 사용하지 않고, 적절한 압축 설정을 적용합니다. (예: 노멀맵은Normalmap압축, 컬러는 용도에 맞는Default설정과 플랫폼별 실제 압축 포맷 확인)
- 재강조: 9장 2절에서 다룬 텍스처 해상도(Max Texture Size)와 압축 설정(
-
메시 LOD 및 디시메이션
- 재강조: 메시의 폴리곤 수가 많을수록 메모리에 더 많은 버텍스 데이터가 저장됩니다. LOD는 주로 그릴 삼각형 수를 줄입니다. 여러 LOD 데이터 자체는 메모리를 추가 사용하며, 실제 상주 메모리 감소는 스트리밍·언로드 여부로 확인합니다.
-
오디오 압축
- 설정: 오디오 에셋(
Sound Wave) 더블클릭 후Details패널의Compression Settings를 조정합니다. - 활용: 대상 플랫폼이 지원하는 코덱과 압축 품질·스트리밍 설정을 비교합니다. 길이만으로 포맷을 고정하지 말고 디코딩 CPU 비용, 메모리, 시작 지연과 음질을 함께 확인합니다.
- 설정: 오디오 에셋(
-
애니메이션 압축
- 설정: 스켈레탈 메시의 애니메이션 시퀀스(
Animation Sequence) 에셋에서Compression섹션을 조정합니다. - 활용: 사용 버전의 Bone/Curve Compression Settings를 비교해 파일 크기·메모리와 동작 오차를 확인합니다.
Compress None같은 비압축 선택을 용량 절감으로 가정하지 않습니다.
- 설정: 스켈레탈 메시의 애니메이션 시퀀스(
에셋 로딩 및 언로딩
-
스트리밍 (Streaming) 레벨
- 역할: 레벨 전체를 한 번에 로드하는 대신, 플레이어가 특정 영역에 진입했을 때 해당 레벨 섹션만 로드하고, 벗어나면 언로드하여 메모리 사용량을 관리합니다.
- 활용: 넓은 월드에서 로드 범위를 제한하는 데 유용하며, World Partition 사용 여부에 따라 관리 방식이 달라집니다.
- 설정: 전통적인 서브 레벨은
Window > Levels에서 관리합니다.Always Loaded는 계속 로드되므로 영역별 언로드가 필요하면 적절한 스트리밍 방식을 선택합니다. World Partition 월드는 셀과 스트리밍 소스를 사용합니다.
-
비동기 에셋 로딩 (Asynchronous Asset Loading)
- 역할: 게임이 실행되는 동안 필요한 에셋(메시, 텍스처 등)을 백그라운드에서 로드하여 동기 로드로 인한 메인 스레드의 정지를 줄입니다. 객체 초기화·완료 처리 등으로 스파이크가 남을 수 있습니다.
- 활용: 로딩 화면 없이 끊김 없는 게임 플레이를 구현할 때 중요합니다.
- 구현: Soft Object/Class Reference와
Async Load Asset/Async Load Class Asset노드를 사용하고 완료 후 결과 유효성을 확인합니다. 동기Load Asset과 구분합니다.
-
가비지 컬렉션 (Garbage Collection)
- 역할: 강한 참조 등 도달 가능성에 따라 회수 가능한 UObject를 정리합니다. 참조가 유지된 에셋은 화면에 없다는 이유만으로 회수되지 않습니다.
- 설정:
Project Settings > Engine > Garbage Collection에서Time Between Purging Pending Kill Objects등 제공되는 설정을 확인합니다. 이 값은 pending-kill 참조 정리 간격이며 모든 GC 동작을 단일 주기로 설명하지 않습니다. - 강제 GC: 특정 시점(예: 레벨 전환)에
Collect Garbage노드를 호출하여 명시적으로 가비지 컬렉션을 실행할 수 있습니다. (CPU 스파이크 유발 가능성 있음)
인스턴싱 (Instancing)
- 역할: 동일한 메시를 여러 번 반복해서 배치할 때, 메시·머티리얼 데이터를 공유해 컴포넌트와 렌더 제출 비용을 줄이는 기법입니다. 섹션·패스·LOD 등에 따라 실제 드로우 콜은 여러 개일 수 있습니다.
- 활용: 나무, 풀, 돌멩이, 동일한 건물 부품 등 반복적으로 사용되는 스태틱 메시에 사용합니다.
- 컴포넌트:
Hierarchical Instanced Static Mesh Component (HISM)또는Instanced Static Mesh Component (ISM)컴포넌트를 사용하여 구현합니다. 공유 메시 외에 인스턴스 트랜스폼과 커스텀 데이터·컬링 등 관리 데이터도 저장합니다. ISM/HISM의 LOD·컬링 차이와 Nanite 사용 여부에 따라 효과를 비교합니다.
CPU 사용량 최적화
CPU는 게임 로직과 주요 업데이트를 담당하므로, 비효율적인 로직은 프레임 드랍의 주요 원인이 됩니다.
블루프린트 및 C++ 로직 최적화
-
Event Tick활용 최소화- 핵심:
Event Tick은 매 프레임마다 호출되므로, 여기에 복잡한 로직을 넣는 것은 CPU 부하를 크게 증가시킵니다. - 대안:
Set Timer by Event를 사용하여 주기적인 업데이트 로직을 0.1~0.5초 간격으로 실행하거나, 특정 이벤트(예: 플레이어 입력, 충돌)가 발생할 때만 로직을 실행합니다. - 활용: 오브젝트 상태 확인, UI 업데이트, AI 행동 업데이트 등.
- 핵심:
-
루프(Loop) 최적화
For Loop,For Each Loop등 반복문 내부에 너무 많은 연산이나 복잡한 함수 호출을 피합니다.- 대규모 배열을 순회하는 경우, 필요한 경우에만 루프를 실행하도록 조건을 추가합니다.
-
IsValid및Branch노드 활용IsValid노드를 사용하여 유효하지 않은 오브젝트에 접근하는 것을 방지하고,Branch노드를 사용하여 불필요한 로직이 실행되지 않도록 합니다.
-
캐싱(Caching) 참조
Get Actor Of Class,Get All Actors Of Class와 같이 레벨에서 특정 액터를 검색하는 노드는 비용이 높습니다. 필요한 시점에 검색해 참조를 캐싱하고, 액터 생성·파괴나 레벨 전환 시 갱신·유효성을 확인합니다.
-
불필요한 디버그 출력 제거
Print String,Draw Debug등의 디버그 노드는 개발 중에는 유용하지만, 최종 빌드에서는 제거하거나 비활성화해야 합니다. (개발 중에는Development Build에서만 활성화되도록 할 수 있음)
물리 시뮬레이션 최적화
- 재강조: 7장 5절 물리 시뮬레이션 성능 조정에서 다룬 내용입니다. 물리 시뮬레이션은 CPU에 큰 부담을 줍니다.
Simulate Physics활성화 오브젝트 수 제한.Simple Collision적극 활용.- 물리 오브젝트 자동
Sleep기능 활용. Max Physics Delta Time,Max Substeps등의 프로젝트 설정 조정.
AI (인공지능) 최적화
- 재강조: AI가 병목으로 측정되면 업데이트 빈도와 활성 범위를 확인합니다.
- 거리 기반 AI 비활성화: 플레이어로부터 멀리 떨어진 AI는 행동 로직을 비활성화하거나, 매우 단순한 로직만 실행하도록 합니다.
- 행동 트리/블랙보드 최적화: 복잡한 행동 트리(Behavior Tree) 노드의 실행 빈도를 줄이고, 블랙보드(Blackboard) 쿼리 빈도를 최적화합니다.
- 내비게이션 메쉬 (Nav Mesh) 최적화: 필요한 영역에만
Nav Mesh를 생성하고, 복잡도를 단순화합니다.
드로우 콜 (Draw Call) 최적화
- 재강조: 9장 2절에서 다룬
Merge Actors및Instancing은 CPU의 드로우 콜 준비 작업 부담을 줄입니다.- 배칭 (Batching): 호환되는 메시·머티리얼·셰이더 바인딩의 드로우 병합을 지원하지만, 단순히 가까이 있다는 이유로 자동 배칭되지는 않습니다. 실제 드로우 수를 확인합니다.
- 어트라스 (Atlases): 여러 작은 텍스처를 하나의 큰 텍스처(텍스처 아틀라스)에 묶어 사용하여 머티리얼 수를 줄이고 드로우 콜을 절약할 수 있습니다.
메모리 및 CPU 사용량 분석 도구
Stat Unit:Game(CPU 로직) 및Draw(CPU 드로우 콜) 시간을 통해 CPU 병목을 1차적으로 확인합니다.Stat Engine: 전반적인 엔진 통계를 보고, 개별 함수 비용은 해당 Stat 그룹과 Timing Insights에서 추적합니다.Stat Memory: 엔진 서브시스템의 메모리 통계를 봅니다. GPU 리소스는Stat RHI·플랫폼 도구와 함께 확인하며, 서로 다른 통계의 포함 범위를 구분합니다.Memreport(콘솔 명령어):memreport -full을 콘솔에 입력하면 현재 메모리 사용량에 대한 상세한 보고서가 출력 로그 또는 파일로 생성됩니다. 어떤 에셋이 가장 많은 메모리를 차지하는지 확인할 수 있습니다.-
Unreal Insights(언리얼 인사이트)- 역할: 언리얼 엔진 4.23 버전부터 제공되는 강력한 프로파일링 도구입니다. CPU, GPU, 메모리, 네트워킹 등 엔진의 거의 모든 활동을 시각적으로 상세하게 분석할 수 있습니다.
- 사용법: CPU/GPU 등 필요한 trace 채널을 활성화하고 결과를
UnrealInsights.exe에서 엽니다. 메모리 분석은 Development 실행 파일을 시작할 때-trace=default,memory를 지정해 할당 초기부터 기록합니다. 에디터와 패키지의 측정은 구분합니다. - 활용: 특정 프레임에서 발생하는 CPU 스파이크의 원인(어떤 블루프린트 함수가 가장 오래 걸렸는지), 메모리 할당 패턴 등을 매우 상세하게 시각적으로 분석할 수 있습니다. (고급 기능)
- 원격 장치: 지원되는 Insights trace 또는 플랫폼 프로파일러로 수집합니다. Session Frontend의 기능과 제공 여부는 엔진 버전을 확인합니다.
반복 플레이에서 비교할 항목
| 증상 | 확인할 근거 |
|---|---|
| 메모리 증가 | 같은 이동 경로의 시작·피크·종료 시점, memreport와 할당/해제 추적 |
| Game 스파이크 | Tick·AI·물리·생성/파괴·GC의 호출 시간 |
| Draw 증가 | 제출·컴포넌트·머티리얼 섹션과 렌더 스레드 대기 |
| 이동 중 멈춤 | 로드 요청·완료 처리·스트리밍 경계의 시간 |
변경 한 가지를 적용한 뒤 같은 구간에서 비교하고, 레벨 전환·장시간 플레이·백그라운드 복귀에서도 회수와 기능이 유지되는지 확인합니다.