성능 분석 준비 (Profiling Preparations)
성능 분석을 시작하기 전에 설정이 올바르게 되어있는지 확인하세요. 다음은 성능 분석 시 고려해야 할 간단한 체크리스트입니다. vsync와 다른 프레임 레이트 기능을 비활성화하세요. 베이킹되지 않은 조명은 성능에 큰 영향을 미치고 분석 결과를 왜곡시킬 수 있습니다. 이는 성능 분석 시 더 느린 렌더링 경로를 사용하기 때문입니다.
이상적으로는 Unreal Insights와 같은 도구로 성능을 분석할 때 에디터 내에서 실행하는 것보다 게임을 패키징하여 실행해야 합니다. 메모리 사용량과 더 많은 렉이 발생하는 레벨 스트리밍 외에도, 에디터 빌드에서의 프레임 시간은 상당히 다를 수 있습니다. '독립형' 모드에서 게임을 실행하는 것도 여전히 매우 편리하며, 이 경우 에디터 뷰포트의 '실시간' 기능이 비활성화되고 최소화되어 있는지 확인하세요.
- r.vsync 0
- t.maxfps 0
- SmoothFrameRate = false (Project Settings) SmoothFrameRate 비활성화 (프로젝트 설정)
- Lighting Built & MapCheck Errors resolved 조명 베이킹 및 맵 체크 오류 해결
- Packaged Game build 패키징된 게임 빌드
- Editor 'Standalone' is convenient (however memory and certain timings may be inaccurate) 에디터 '독립형' 모드가 편리함 (그러나 메모리와 특정 타이밍이 부정확할 수 있음)
병목 현상 찾기 (Find the Bottleneck)
프로젝트 코드를 맹목적으로 최적화해서는 안 됩니다. 대신 측정을 수행하고 병목 현상을 찾아내세요. 게임, 렌더링 및 GPU는 모두 비동기적으로 실행되므로, 어떤 부분이 병목 현상을 일으키는지 이해하는 것이 중요합니다. 그렇지 않으면 의미 있는 성능 향상을 볼 수 없을 것입니다.
- Game Thread / Render Thread / GPU
- Unreal Insights
- ProfileGPU + r.RHISetGPUCaptureOptions 1
- stat unitgraph
- stat detailed
- r.screenpercentage 20
- pause (Freeze Game Thread) pause (게임 스레드 일시 정지)
- Memory & Loading 메모리 및 로딩
- Unreal Insights (-trace=memory,loadtime,file)
- memreport -full
- loadtimes.dumpreport
언리얼 인사이트 (Unreal Insights)
언리얼 인사이트는 최신 플래그십 성능 분석 도구로, 언리얼 엔진 4 후기에 도입되었으며 5.0 버전에서는 고급 메모리 분석 기능 추가와 같은 큰 개선이 이루어졌습니다.
- 프레임 타이밍에 대한 상세 정보:
- 단일 프레임 또는 세션에 대한 심층 분석
트레이스 채널 (Trace Channels)
게임 실행 파일이나 독립 응용 프로그램에서 사용되는 일반적인 트레이스 채널입니다. statnamedevents 매개변수는 객체 이름에 대한 더 자세한 정보를 제공합니다.
- trace=log,cpu,gpu,frame,bookmark,loadtime,file,memory,net
- statnamedevents
북마크 (Bookmarks)
북마크는 분석 세션 중 발생하는 변화와 전환에 대한 컨텍스트 정보를 추가할 수 있습니다. 여기에는 새 레벨 스트리밍, 콘솔 명령 실행, 시퀀서 시작 등이 포함됩니다. 자신의 게임 코드에서 새 북마크를 쉽게 추가하여 더 많은 컨텍스트를 제공할 수 있습니다. 분석 시 bookmark 트레이스 채널을 사용하세요.
- 컨텍스트 및 전환을 위한 북마크
- GC (Garbage Collection) 가비지 컬렉션
- Sequencer Start 시퀀서 시작
- Level streaming (Start/Complete) 레벨 스트리밍 (시작/완료)
- Console Commands 콘솔 명령
**TRACE_BOOKMARK**(Format, Args)
새로운 "stat" 프로파일링 추가 (Add new 'stat' profiling)
C++ 게임 코드에서는 자체 상태 추적을 추가하여 추가적인 프로파일링 세부 정보를 포함하는 것이 가치 있을 수 있습니다. 기본적으로 블루프린트 함수는 "Blueprint Time"으로만 표시되지만, 사용자 정의 프로파일링을 추가하면 블루프린트가 C++ 게임 코드를 호출하는 경우 이 시간이 어떻게 소비되는지에 대한 더 많은 세부 정보가 추가됩니다. 이는 비교적 간단하며, 자세한 내용은 아래 블로그 게시물을 참조하세요.
- 게임 코드에 프로파일링 세부 정보 추가
- 뷰포트나 인사이트를 통해 "stat YourCategory"로 추적
이 주제에 대해 이전에 작성한 글:
Adding Stat Traces (Stat Commands) in Unreal Engine
이전에 '성능 통계(통계 명령)' 글에서 이 주제를 다룬 적이 있습니다.
언리얼 인사이트 팁 (Unreal Insight Tips)
성능 분석 세션 중에 몇 가지 명령을 실행하면 이것이 프레임 레이트에 어떤 영향을 미치는지 자세히 볼 수 있습니다. 특히 일부 기능은 먼저 게임 스레드에서 처리된 다음 같은 프레임의 후반부에 렌더링 스레드에서 처리됩니다(예: 스켈레탈 메시).
- 세션 중에 비교를 위한 명령 실행 (북마크로 표시됨)
- r.ScreenPercentage 20
- pause
- 오버헤드를 줄이기 위해 필요한 트레이스 채널만 사용
- 게임플레이 컨텍스트를 위한 사용자 정의 북마크 추가
메모리 보고서 - 전체(Memreport -full)
이것은 메모리 사용 현황과 의도치 않게 로드된 리소스가 있는지 심층적으로 이해하는 데 도움이 됩니다. obj listclass=를 사용하여 특정 리소스 유형을 자세히 살펴보면, 가장 비용이 많이 드는 리소스에 대한 상세 정보를 제공합니다. 이 정보를 통해 최적화가 필요한 리소스를 파악하고, 해당 시점에 메모리에 유지할 필요가 있는지 검토할 수 있습니다.
- memreport -full
- 메모리 프로파일링을 위한 여러 개별 명령을 실행합니다
- obj list class=
- 예시: obj list class=AnimSequence
- 정확한 결과를 위해 패키지 빌드에서만 사용
- 예시: AnimSequence는 에디터 빌드에서 두 배 크기입니다.
DumpTicks
DumpTicks는 게임 스레드 성능을 최적화하는 데 탁월한 첫 번째 단계입니다. 틱 중인 모든 객체를 내보내서 어떤 객체가 틱해야 하는지 또는 비활성화할 수 있는지 검토합니다.
- dumpticks / dumpticks grouped
- 모든 액터 및 컴포넌트 틱을 출력합니다
- listtimers
- 낮은 빈도로 실행
- 과도한 부하 방지(끊김 현상)
- stat uobjects
- Significance Manager를 사용하여 추가로 비활성화/감소
- 이에 대해서는 나중에 더 자세히...
충돌 및 물리(Collision & Physics)
기본적으로 장면의 메시는 물리와 충돌이 모두 활성화되어 있습니다. 물리를 사용하지 않는 경우, 특히 많은 메시가 이동 중인 경우 이는 낭비가 될 수 있습니다. 플레이어 이동에는 객체에 대해 "쿼리만(QueryOnly)"만 필요하므로, 사용되지 않는 물리체를 로드하고 유지하기 위해 CPU와 메모리를 낭비하고 있을 수 있습니다.
- 언리얼은 기본적으로 바로 작동하도록 구성되어 있습니다.
- "충돌 활성화" => 물리 + 쿼리
- 대부분의 경우 '쿼리만(QueryOnly)'만 필요합니다.
- 플레이어가 도달하거나 상호작용할 수 없는 컴포넌트를 비활성화하세요.
- 성능 분석
- stat physics
- stat collision
- obj list class=BodySetup
- show CollisionPawn
- show CollisionVisibility
팁: 랜드스케이프는 더 낮은 충돌 MIP를 사용할 수 있습니다.
씬 컴포넌트 이동하기(Moving SceneComponents)
많은 SceneComponents가 있는 게임 오브젝트를 이동하는 것은 결코 무료가 아닙니다. 특히 기본 설정을 사용하는 경우에는 더욱 그렇습니다. CPU 비용을 크게 줄일 수 있는 몇 가지 간단한 최적화가 있습니다.
- 프레임당 한 번만 이동/회전하기
- 충돌 비활성화 & GenerateOverlaps=False
- AutoManageAttachment 자동 첨부 관리
- 오디오 & 나이아가라
- 프로파일링
- stat component
SetActorLocation과 SetActorRotation이 별도로 호출되어 두 개의 큰 노란색 "MoveComponent" 섹션이 나타납니다.
컴포넌트 경계(Component Bounds)
각 컴포넌트의 비용이 높지 않더라도 하나의 블루프린트에 많은 컴포넌트가 있으면 비용이 누적될 수 있습니다. 부모 컴포넌트의 경계를 재사용할 때는 신중하게 고려해야 합니다. 객체가 애니메이션에서 경계를 벗어날 때 렌더링 깜빡임이 발생할 수 있으며, 특히 카메라가 객체에서 멀어질 때 더욱 두드러집니다.
- UseAttachParentBound=True
- "CalcBounds" 계산 건너뛰기
- show Bounds 또는 showflag.bounds 1
중요도 관리자(Significance Manager)
중요도 관리자는 게임 오브젝트의 "중요도" 값을 계산하고 실시간으로 기능을 줄이기 위한 기본 프레임워크를 제공합니다. 원거리 AI 에이전트의 틱 속도를 낮추거나, 충분히 가까워지면 애니메이션을 완전히 비활성화할 수 있습니다. 이 시스템은 게임에 매우 특화되어 있으며, 트리거 볼륨에 의존하여 게임 오브젝트를 비활성화할 수 없는 비선형 경험에 특히 유용합니다.
중요도 관리자는 일반적으로 간략하게만 언급되지만 시작하기 어려울 수 있습니다. 현재 블로그 게시물을 작성 중이며 GitHub에 일부 예제 코드를 제공하고 있습니다. 요구 사항에 따라 구현이 상당히 간단할 수 있으므로 탐색할 가치가 있는 시스템입니다!
- 게임별 로직에 기반한 충실도 조절
- 거리 기준
- 최고 품질의 최대 오브젝트 수('버킷')
- 게임 오브젝트를 축소하기 위한 '중요도 값' 계산
- 예시: NPC, 퍼즐 액터, 차량, 다른 플레이어
- 감소/제거:
- 틱 속도
- 트레이스 / 쿼리
- 애니메이션 업데이트 (SKs)
- 오디오/파티클 재생 또는 업데이트 속도
- 프로파일링
- ShowDebug SignificanceManager
- sigman.filtertag <name>
- stat significancemanager 통계
- 예시
https://github.com/tomlooman/ActionRoguelike
- USSignificanceComponent.h
오클루전 컬링(Occlusion Culling)
오클루전 컬링은 일반적으로 프레임 렌더링에서 비용이 많이 드는 부분이며, 이 비용을 증가시키는 요소와 사용 가능한 최적화 도구를 이해하지 못하면 다루기 어려울 수 있습니다. 가장 간단한 방법은 고려해야 할 원시 요소의 수를 줄이는 것입니다. 이는 레벨 스트리밍, HLOD 및 거리 기반 컬링이 크게 도움이 되는 부분입니다.
- 시야 컬링 및 오클루전 쿼리
- 다음 프레임에서 폴링되는 GPU 쿼리 결과
- HLOD는 오클루전 비용을 크게 줄일 수 있습니다(아래 참조)
- 프로파일링
- r.visualizeoccludedprimitives 1
- stat initviews
모듈식 메시 구축, 많은 가려진 부분
정적 지오메트리에서 생성된 단일 HLOD.
RenderDoc: 오클루전 쿼리 결과
RenderDoc는 언리얼이 프레임을 어떻게 렌더링하는지 분석하고 이해하는 데 매우 유용한 도구입니다. 이 예시에서는 깊이 테스트를 사용하여 오클루전 쿼리 결과를 시각화했습니다. 수백 개의 쿼리가 몇 픽셀 크기의 박스에 대해 전송되는 것을 발견할 수 있는데, 이는 성공할 가능성이 거의 없거나 렌더링 후 작은 메시가 프레임에 중요하지 않을 수 있습니다.
- DepthTest RenderDoc의 오버레이
- 작거나 먼 객체에 대한 '낭비적인' 쿼리를 쉽게 찾기
거리 컬링(Distance Culling)
거리 컬링은 오클루전 비용을 효과적으로 줄이는 방법입니다. 작은 소품은 인스턴스 설정을 사용하거나 거리 컬링 볼륨을 사용하여 객체 크기와 컬링 거리를 매핑할 수 있습니다. 이 방식으로 컬링된 객체는 GPU 오클루전 쿼리가 필요하지 않아 비용을 크게 줄일 수 있습니다.
**https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/VisibilityCulling/CullDistanceVolume/**docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/VisibilityCulling/CullDistanceVolume/
- PrimitiveComponent: 최대/최소 그리기 거리
- 라이트 콘, 안개 볼륨, 블루프린트 컴포넌트
- 거리 컬링 볼륨
- 객체 "크기"와 "컬링 거리"를 매핑
- 오클루전 쿼리 비용 감소
- 프로파일링
- showflag.distanceculledprimitives 1
- stat initviews
최소/최대 그리기 거리(Min/Max Draw Distance)
MinDrawDistance는 카메라에 가까울 때 많은 오버드로우를 발생시키지만 장면에 큰 기여를 하지 않는 반투명 표면을 컬링하는 데 사용될 수 있습니다(예: 카메라에 가까울 때 페이드 아웃되는 재질은 여전히 픽셀 평가가 필요함).
- 예시: 라이트 콘
- 시각화: 셰이더 복잡도
- 픽셀 오버드로우
- DistanceCullFade 거리 컬링 페이드
- 0-1, 1-0 블렌딩
기본 장면, 많은 중첩 표면
최소+최대 그리기 거리 설정
렌더링 프리징(FreezeRendering)
장면이 올바르게 가려지는지 또는 일부 액터가 예기치 않게 렌더링되는지 확인하기 위해 오클루전 컬링을 프리징합니다.
- 'FreezeRendering' + ; (세미콜론)을 사용하여 DebugCamera로 날아다니기
- 오클루전이 예상대로 작동하는지 확인
플레이어가 건물을 향함
렌더링 프리징 활성화됨
라이트 컬링(정적 및 이동 가능)
라이트는 장면에 기여하지 않거나 기여도가 낮더라도 렌더링 스레드에 상당한 비용을 추가할 수 있습니다. 먼 거리에서 페이드 아웃하는 것이 도움이 될 수 있으며, 절대적으로 필요한 경우가 아니면 변경하거나 이동하지 않도록 하세요. 고정 라이트가 너무 많이 겹치지 않도록 하세요(최대 4개). 그렇지 않으면 그 중 하나가 강제로 이동식이 되어 프레임에 상당한 비용이 추가됩니다.
- 자동 화면 크기 컬링이 충분히 엄격하지 않음
- MinScreenRadiusForLights (0.03)
- 사례별 조기 컬링
- MaxDrawDistance 최대 그리기 거리
- MaxDistanceFadeRange 최대 거리 페이드 범위
- 프로파일링
- Show > LightComplexity (Alt+7) 표시 > 라이트 복잡도(Alt+7)
- Show > StationaryLightOverlap 표시 > 정적 라이트 중첩
ToggleLight 라이트 토글 <부분 이름>
너무 많은 정적 라이트 중첩
레벨 스트리밍
레벨 스트리밍은 레벨 디자인 초기 단계에서 고려해야 하며, 나중에 문제가 발생하지 않도록 해야 합니다. 여기에는 레벨 부분을 서브레벨로 분할하고 이러한 레벨을 언제 로드/언로드할지 고려하는 것이 포함됩니다.
**https://docs.unrealengine.com/4.27/en-US/BuildingWorlds/LevelStreaming/**docs.unrealengine.com/4.27/en-US/BuildingWorlds/LevelStreaming/
메모리 로드를 크게 줄이는 것 외에도, 가능한 한 많은 레벨을 오랫동안 숨기거나(또는 완전히 언로드하여) 오클루전 비용을 크게 줄일 수 있습니다. bShouldBeVisible은 C++/블루프린트에서 레벨을 숨기는 데 사용할 수 있습니다. 이렇게 하면 메모리에 유지되지만 오클루전 등을 고려하지 않습니다.
- 스트리밍 볼륨 vs. 수동 로드/언로드
- 카메라 위치 기반(주의: 3인칭 뷰 및 시네마틱 샷)
- 특정 서브레벨에서 두 가지를 결합할 수 없지만 게임 내에서 혼합 가능
- 프로파일링
- stat levels
- Loadtimes.dumpreport (+ loadtimes.reset)
- 언리얼 인사이트
- 레벨 로드 및 "GC" 북마크 찾기
- loadtime,file 트레이스 채널
- 성능 영향
- 초기 레벨 로드 시간
- 오클루전 비용
- 메모리
- 옵션: Load, LoadNotVisible, LoadVisible
- 렌더러를 돕기 위해 숨기는 동안 메모리에 유지
- 레벨 디자인 초기에 스트리밍을 고려하세요!
- 여러 ULevel로 분할여러 ULevel로 분할
- 시야선, 자연적인 통로 및 돌아올 수 없는 지점시야선, 자연적인 통로 및 돌아올 수 없는 지점
애니메이션(Animation)
다음 애니메이션 최적화 문서 페이지에는 강연에서 언급된 기법에 대한 더 많은 정보가 포함되어 있습니다.
Animation Optimizationdocs.unrealengine.com/5.0/en-US/animation-optimization-in-unreal-engine/
빠른 경로(Fast Path)
- AnimGraph에서 EventGraph로 계산을 이동하여 '빠른 경로' 허용
- WarnAboutBlueprintUsage를 사용하여 AnimGraph에서 경고 받기
- 프로파일링
- stat anim
빠른 성과(Quick Wins)
스켈레탈 메시는 CPU 스레드에 상당한 처리량을 추가합니다. 많은 스켈레탈 메시가 동시에 존재할 때, 특히 항상 프레임에 기여하지 않는 경우 시도할 수 있는 간단한 최적화 방법이 있습니다.
- 원거리 스켈레탈 메시를 위한 업데이트 속도 최적화(URO)
- VisibilityBasedAnimTickOption (클래스별 및 DefaultEngine.ini의 구성 변수)
- OnlyTickPoseWhenRendered - 렌더링 될 때만 포즈 업데이트
- AlwaysTickPoseAndRefreshBones - 항상 포즈 업데이트 및 뼈 새로고침
- ...
- 더 많은 불리언!
- bRenderAsStatic
- bPauseAnims
- bNoSkeletonUpdate
Oodle 데이터 및 Oodle 텍스처
Oodle은 오랫동안 놀라운 압축을 제공해 왔으며, 최근에는 언리얼과 함께 제공됩니다. 게임 패키지 크기를 크게 개선할 수 있으며, 더 빠른 압축 해제를 통해 로딩 시간도 향상시킬 수 있습니다!
**https://docs.unrealengine.com/4.27/en-US/TestingAndOptimization/Oodle/**docs.unrealengine.com/4.27/en-US/TestingAndOptimization/Oodle/
- RDO(Rate Distortion Optimization) 압축
- 기본 설정과 비교하여 압축 효과 크게 향상
- 압축 시간이 더 오래 걸림(기본적으로 에디터에서는 비활성화)
- RDO는 텍스처 데이터를 '준비'하여 Oodle 데이터와 함께 작동
합성 벤치마크(SynthBenchmark)
확장성은 게임이 다양한 기기에서 실행될 수 있도록 하는 핵심 개념입니다. 하드웨어 벤치마크 도구는 게임이 실행되는 기기의 성능을 평가하고 기본 확장성 레이어(그림자 렌더링, 시야 거리 등의 카테고리에서 낮음에서 에픽까지)를 적용하는 데 도움이 됩니다.
기본 확장성을 위한 하드웨어 벤치마크 적용에 관한 블로그 글을 작성했습니다.
**https://www.tomlooman.com/unreal-engine-optimal-graphics-settings/**www.tomlooman.com/unreal-engine-optimal-graphics-settings/
- CPU/GPU 벤치마크 실행 및 확장성 설정 적용
- 평균 CPU/GPU에 대해 기준 100으로 "점수" 반환
그림자 프록시(Shadow Proxies)
그림자 프록시 사용은 장면에서 일반적으로 상당한 그림자 렌더링 비용을 줄이기 위한 수동 프로세스입니다. 아름답고 모듈식 건물이 있을 수 있는데, 이로 인해 많은 드로우 콜과 그림자 깊이 렌더링에만 사용되는 수백만 개의 삼각형이 발생할 수 있습니다. 이 시스템의 주요 단점은 수동적이고 파괴적인 워크플로우입니다. 그럼에도 불구하고 이 기법을 지적하고 싶으며, UE5의 지오메트리 스크립트를 사용하면 몇 개의 노드만으로 단순화된 메시 프록시를 실시간으로 생성할 수 있습니다!
- 단일 로우 폴리 실루엣 메시
- RenderMainPass=False
- 맞춤형 메시 또는 내장 메시 도구 사용
- '액터 병합'(레벨에서 에셋 우클릭)
- UE5 지오메트리 스크립트
- 프로파일링
- Insights의 'ShadowDepths'
- ProfileGPU + r.RHISetGPUCaptureOptions 1
사이즈맵(디스크 및 메모리)
SizeMap은 콘텐츠의 하드 레퍼런스를 빠르게 찾고 해결하는 데 매우 유용한 도구입니다. 이는 종종 숨겨진 위험으로, 프로젝트 후반에 메모리와 로딩 시간에 어려움을 겪을 때 상당한 개발 비용을 추가할 수 있습니다.
- 예상치 못한 참조와 비대해진 콘텐츠 찾기
- 블루프린트와 (서브)레벨에 일찍 자주 사용
마크 크레이그의 에셋 의존성 체인의 숨겨진 위험에 관한 최근 강연을 확인하세요.
**https://www.youtube.com/watch?v=4-oRyDLfo7M**www.youtube.com/watch?v=4-oRyDLfo7M
통계 창(Statistics Window)
저는 메모리와 총 맵 크기의 기회를 조사하기 위해 이 패널을 자주 사용합니다. 특히 랜드스케이프 에셋은 거대한 비대 에셋으로 표시됩니다. 충돌 복잡성을 줄이고 보이지 않는 랜드스케이프 컴포넌트를 제거하는 것이 여기에서 큰 도움이 됩니다. 레벨에서 한 번만 사용되는 특정 에셋 변형을 발견할 수 있으며, 이러한 에셋이 메모리와 로딩 화면을 차지하지 않도록 교체하는 것을 고려해 볼 수 있습니다!
- 현재 레벨의 통계
- 프리미티브 통계
- 텍스처 통계
- 팁: 보조 정렬을 위해 Shift 클릭
- '개수' + '삼각형' 또는 '크기' 정렬(한 번만 사용되는 큰 에셋 찾기)
유용한 콘솔 명령어
- ToggleForceDefaultMaterial(비 Nanite)
- 모든 것이 동일한 셰이더로 렌더링될 수 있으므로 BasePass 비용에 큰 변화를 보여줍니다. 이를 사용하여 장면을 비교하고 셰이더가 미치는 영향을 확인할 수 있습니다.
- stat Dumphitches
- 성능 문제 프로파일링은 어려울 수 있으며, 이는 문제가 발생했을 때 비용이 많이 드는 함수 호출을 찾는 첫 번째 단계입니다.
- stat none (화면에서 모든 카테고리 지우기)
- r.ForceLODShadow X(비 Nanite)
- 저사양 플랫폼의 경우, 그림자를 위해 렌더링되는 삼각형을 크게 줄이는 간단한 트릭 중 하나입니다. 좋은 LOD가 있는지 확인하세요! (비 nanite, 비 VSM, VSM은 더 나은 LOD 바이어스(r.Shadow.NaniteLODBias) 옵션이 제공됩니다.)
원문
https://zhuanlan.zhihu.com/p/1897442074363667675
'TECH.ART.FLOW.IO' 카테고리의 다른 글
[번역][연재물] 언리얼 엔진 개발 가이드. 파티클 시스템. 파트1 (0) | 2025.06.30 |
---|---|
[번역][따로 정리추가] 모바일에서의 언리얼 엔진 "Panner" 노드 정확도 및 퍼포먼스 문제 분석 (0) | 2025.06.12 |
앙상블 스타즈 IP 구축 전략은? (8) | 2025.06.10 |
Message part 1 (0) | 2025.06.09 |
[번역][연재물] 언리얼 엔진 개발 가이드. 플러그인 개발 (0) | 2025.06.06 |