Sparta Unreal 부트캠프 102일차

정찬호·2026년 4월 27일

QA 분반


플레이 영상을 보며 게임 분석하기

파쿠르 + 캐릭터 커스터마이징(체형, 피부색, 머리, 옷 등) + 기본 멀티플레이 + 유적 탐사 + 팀원 소생 기능 맵에 힌트 존재 + 다양한 퍼즐 요소 + 디스트럭터블 메쉬를 사용한 무너지는 계단 + 함정(외부에서 꺼내줘야 함) + 연료를 채워서 다음으로 넘어가는 것 + 특정 미션에서 카메라 시점 변환(탑뷰) + 몬스터 존재(늑대인간, 골렘, 거인 등) + 상호작용으로 사망자의 아이템 획득?(사망자 시체 삭제) + 낙하 데미지 존재 + 인게임 보이스 채팅 존재(생존자는 사망자의 소리를 듣지 못함)

퍼즐을 풀어 맵의 다음 영역을 해금하고, 맵에 흩뿌려진 연료 아이템과 힌트 아이템을 주워서 다음 스테이지로 넘어가기 위한 조건을 달성하는 게임입니다. 다음 스테이지로 넘어가기 위해서는 충분한 연료와 힌트 3개가 필요하다고 합니다.

플레이 영상 중간에 핀볼 미션이 4인 진행인 것으로 보아, 최소 4인의 플레이어가 필요한 멀티플레이 게임으로 보입니다.

멀티플레이, 퍼즐, 생존, 수집?
난이도가 상당히 높아보였습니다.

테스트 영상의 플레이 시간은 70분 정도


앞으로의 분석에 관해서

BP와 애니메이션 까지 분석하기에는 2주에 시간이 촉박하다고 하셨습니다. C++ 위주로 버그 테스트를 진행합니다.

이번 기회에 AI-Native 역량을 키우기 위해,LLM(클로드 코드)으로 QA 체크리스트 생성 및 뽑힌 체크리스트 검토, LLM 출력 로그를 기록하면서 사용법을 학습합니다.


리그레션 테스트(회귀 테스트)

  • 이미 테스트된 프로그램의 테스팅을 반복하는 것으로, 결함 수정 이후 변경의 결과로 새롭게 만들어 지거나, 이전 결함으로 인해 발견되지 않았던 또 다른 결함을 발견하는 테스트

일단 엔진 버전은 5.6이며 플러그인도 많네요.
.uproject 뜯어서 내부 플러인 뭐뭐 있고, 무슨 역할인지 분석도 진행하자!


코드 살펴보기

.uproject

{
	"FileVersion": 3,
	"EngineAssociation": "5.6",
	"Category": "",
	"Description": "",
	"Modules": [
		{
			"Name": "AO",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"AdditionalDependencies": [
				"Engine",
				"AIModule",
				"GameplayAbilities"
			]
		}
	],
	"Plugins": [
		{
			"Name": "ModelingToolsEditorMode",
			"Enabled": true,
			"TargetAllowList": [
				"Editor"
			]
		},
		{
			"Name": "MetaHumanCharacter",
			"Enabled": true
		},
		{
			"Name": "HairStrandsMutable",
			"Enabled": true
		},
		{
			"Name": "MutableClothing",
			"Enabled": true
		},
		{
			"Name": "OnlineSubsystem",
			"Enabled": true
		},
		{
			"Name": "OnlineSubsystemUtils",
			"Enabled": true
		},
		{
			"Name": "OnlineSubsystemSteam",
			"Enabled": true
		},
		{
			"Name": "SteamSockets",
			"Enabled": true
		},
		{
			"Name": "PoseSearch",
			"Enabled": true
		},
		{
			"Name": "Chooser",
			"Enabled": true
		},
		{
			"Name": "GameplayAbilities",
			"Enabled": true
		},
		{
			"Name": "MotionWarping",
			"Enabled": true
		},
		{
			"Name": "PCG",
			"Enabled": true
		},
		{
			"Name": "PCGGeometryScriptInterop",
			"Enabled": true
		},
		{
			"Name": "DLSSMoviePipelineSupport",
			"Enabled": true,
			"MarketplaceURL": "https://www.unrealengine.com/marketplace/en-US/product/nvidia-dlss"
		},
		{
			"Name": "StreamlineDLSSG",
			"Enabled": false,
			"MarketplaceURL": "https://www.unrealengine.com/marketplace/en-US/product/nvidia-dlss"
		},
		{
			"Name": "DLSS",
			"Enabled": true,
			"MarketplaceURL": "https://www.unrealengine.com/marketplace/en-US/product/nvidia-dlss"
		},
		{
			"Name": "NIS",
			"Enabled": true,
			"MarketplaceURL": "https://www.unrealengine.com/marketplace/en-US/product/nvidia-dlss"
		},
		{
			"Name": "StreamlineReflex",
			"Enabled": false,
			"MarketplaceURL": "https://www.unrealengine.com/marketplace/en-US/product/nvidia-dlss"
		},
		{
			"Name": "StreamlineDeepDVC",
			"Enabled": false,
			"MarketplaceURL": "https://www.unrealengine.com/marketplace/en-US/product/nvidia-dlss"
		},
		{
			"Name": "FSR4MovieRenderPipeline",
			"Enabled": false,
			"SupportedTargetPlatforms": [
				"Win64"
			]
		},
		{
			"Name": "FSR",
			"Enabled": false,
			"SupportedTargetPlatforms": [
				"Win64"
			]
		},
		{
			"Name": "StreamlineCore",
			"Enabled": false,
			"MarketplaceURL": "https://www.unrealengine.com/marketplace/en-US/product/nvidia-dlss"
		},
		{
			"Name": "StateTree",
			"Enabled": true
		},
		{
			"Name": "GameplayStateTree",
			"Enabled": true
		},
		{
			"Name": "ElectraPlayer",
			"Enabled": true
		},
		{
			"Name": "FSRMovieRenderPipeline",
			"Enabled": false,
			"SupportedTargetPlatforms": [
				"Win64"
			]
		}
	]
}

보다시피 플러그인이 엄청 많습니다. NVIDA 관련 플러그인도 있고 AI에 StateTree를 사용했는지 플러그인에 포함되어 있네요. 일단 사용된 플러그인을 한 번 정리해 봐야겠습니다.


플러그인의 종류가 다양해 우선 클로드에게 정리를 부탁했습니다.

[캐릭터 비주얼]          [애니메이션]           [게임플레이]
MetaHuman               PoseSearch             GAS
HairStrandsMutable  →   Chooser           ←→   StateTree
MutableClothing         MotionWarping           GameplayStateTree

[네트워크]               [월드 빌딩]            [렌더링]
OnlineSubsystem         PCG                    DLSS / NIS (활성)
  └ Steam OSS     →     PCGGeometryInterop     StreamlineXX (비활성)
  └ SteamSockets        ModelingTools          FSR (비활성)

[미디어]
ElectraPlayer

언리얼 디벨로퍼 어시스턴트 에게 요청해서 정리받은 내용

  1. 차세대 캐릭터 및 커스터마이징 시스템
    이 그룹은 MetaHuman의 고품질 에셋을 사용하면서, 런타임에 성능 효율적인 방식으로 외형을 변경하는 데 집중합니다.

관련 플러그인: MetaHumanCharacter, HairStrandsMutable, MutableClothing
시스템 관계:
MetaHumanCharacter가 기본 캐릭터 바디와 얼굴(RigLogic) 데이터를 공급합니다.
Mutable 계열 플러그인(HairStrandsMutable, MutableClothing)은 런타임에 여러 메시를 병합하여 드로우 콜을 Eliminate하고, 최적화된 상태로 헤어와 의상을 동적으로 교체합니다.

  1. 애니메이션 및 모션 시스템 (Motion Matching)
    기존의 복잡한 State Machine을 대체하여 캐릭터의 움직임을 훨씬 자연스럽게 만드는 시스템입니다.

관련 플러그인: PoseSearch, Chooser, MotionWarping
시스템 관계:
PoseSearch (Motion Matching): 캐릭터의 미래 경로(Trajectory)를 예측하고 애니메이션 데이터베이스에서 가장 적합한 포즈를 실시간으로 검색합니다.
Chooser: 조건부 로직을 처리하는 에셋입니다. 어떤 애니메이션 데이터베이스를 사용할지, 혹은 어떤 상황에서 특정 동작을 수행할지 결정하는 ‘지능형 선택기’ 역할을 하며 PoseSearch와 긴밀하게 연동됩니다.
MotionWarping: 애니메이션이 재생되는 동안 캐릭터의 위치를 목표 지점(예: 장애물 넘기)에 맞춰 실시간으로 보정합니다.

  1. 게임플레이 프레임워크 및 로직
    AI와 플레이어의 능력 시스템, 복잡한 상태 로직을 관리합니다.

관련 플러그인: GameplayAbilities (GAS), StateTree, GameplayStateTree
시스템 관계:
GameplayAbilities (GAS): 캐릭터의 스킬, 스태츠, 상태 효과(버프/디버프)를 관리하는 강력한 프레임워크입니다.
StateTree: 기존의 Behavior Tree보다 가볍고 효율적인 범용 계층형 상태 머신입니다. GameplayStateTree를 통해 캐릭터의 AI 로직이나 게임 월드의 복잡한 상태 전환을 담당합니다.

  1. 절차적 콘텐츠 생성 (PCG)
    수동 배치 대신 알고리즘을 통해 월드를 구축합니다.

관련 플러그인: PCG, PCGGeometryScriptInterop
설명: 월드 파티션 환경에서 대규모 환경(숲, 바위, 도시 등)을 규칙에 따라 자동 배치합니다. GeometryScriptInterop은 PCG 내에서 복잡한 기하학적 연산을 가능하게 합니다.

  1. 온라인 및 네트워크 서비스
    멀티플레이어 기능과 플랫폼 연동을 담당합니다.

관련 플러그인: OnlineSubsystem, OnlineSubsystemUtils, OnlineSubsystemSteam, SteamSockets
설명: Steam API를 통한 세션 관리, 친구 목록, 매치메이킹 등 온라인 기능을 프로젝트에 통합합니다.

  1. 렌더링 최적화 및 업스케일링 (NVIDIA/AMD)
    성능을 높이기 위한 하드웨어 가속 기술입니다.

관련 플러그인: DLSS, DLSSMoviePipelineSupport, NIS (활성) / FSR, Streamline (비활성)
설명: AI 기반 업스케일링을 통해 고해상도 품질을 유지하면서 프레임 속도를 비약적으로 향상시킵니다. 현재 NVIDIA 계열(DLSS)은 활성화되어 있고, AMD(FSR)는 비활성 상태입니다.

  1. 기타 에디터 및 미디어 도구
    ModelingToolsEditorMode: 에디터 내에서 직접 3D 모델을 수정하거나 생성합니다.
    ElectraPlayer: 게임 내에서 고해상도 비디오를 스트리밍하거나 재생하는 데 사용되는 엔진 내장 미디어 플레이어입니다.

요약 및 제언
이 구성은 “Motion Matching 기반의 고품질 MetaHuman 캐릭터가 GAS와 StateTree로 설계된 지능적인 로직에 따라 움직이며, Steam을 통해 멀티플레이가 가능한 대규모 PCG 월드”를 만드는 데 최적화되어 있습니다.

주의: Mutable 관련 플러그인을 사용할 경우, 캐릭터가 패배하거나 제거되는 Elimination 연출 시 메시가 병합되어 있으므로 개별 파츠 분해보다는 전체적인 머티리얼 효과를 통한 소멸 연출을 권장합니다.

프로젝트 플러그인 구성 분석 - 표 ver.

분류플러그인 명칭주요 역할 및 기능시스템 간 시너지 (관계)
캐릭터 커스터마이징MetaHumanCharacter
HairStrandsMutable
MutableClothing
고품질 캐릭터 베이스 제공 및 런타임 의상/헤어 동적 변경Mutable 시스템이 MetaHuman의 복잡한 메시를 병합하여 드로우 콜을 Eliminate하고 성능 최적화
차세대 애니메이션PoseSearch
Chooser
MotionWarping
Motion Matching 기반의 자연스러운 포즈 선택 및 위치 보정Chooser가 상황에 맞는 데이터베이스를 선택하면, PoseSearch가 최적의 포즈를 검색하여 재생
게임플레이 로직GameplayAbilities (GAS)
StateTree
GameplayStateTree
캐릭터 능력(스킬), 상태 효과 및 고성능 AI/상태 머신 관리StateTree가 전체적인 행동 로직을 결정하고, GAS가 세부적인 수치와 능력치를 처리
월드 제작 (PCG)PCG
PCGGeometryScriptInterop
절차적 알고리즘을 이용한 대규모 환경 자동 생성규칙 기반으로 프롭을 배치하며, GeometryScript로 복잡한 지형지물 연산 지원
온라인/멀티플레이OnlineSubsystemSteam
SteamSockets
OnlineSubsystemUtils
Steam 플랫폼 연동, 세션 관리 및 네트워크 통신Steam API를 통해 친구 초대, 매치메이킹 및 안정적인 데이터 패킷 전송
성능 및 렌더링DLSS
NIS
DLSSMoviePipelineSupport
AI 기반 업스케일링 및 고해상도 출력 최적화렌더링 부하를 줄여 프레임 속도를 높이고 고품질 시네마틱 렌더링 지원
에디터 및 미디어ModelingToolsEditorMode
ElectraPlayer
에디터 내 3D 모델링 및 게임 내 비디오 재생외부 툴 없이 메시 수정이 가능하며, Electra를 통해 고화질 영상 재생

핵심 시스템 관계 요약
성능 최적화 중심: 이 프로젝트는 Mutable을 통해 MetaHuman의 복잡한 구조를 최적화하고, DLSS로 렌더링 부하를 낮추는 등 고품질 그래픽과 성능 사이의 균형을 중시하고 있습니다.
데이터 기반 설계: GAS, StateTree, Chooser의 조합은 하드코딩을 줄이고 에디터 내에서 데이터를 통해 게임플레이 규칙을 유연하게 변경할 수 있는 구조입니다.
애니메이션 혁신: Motion Matching(PoseSearch)을 활성화함으로써 수백 개의 전이(Transition) 노드 없이도 자연스러운 이동 애니메이션 구현이 가능합니다. 캐릭터가 환경에 따라 적절히 반응하며 Elimination(제거) 상황에서도 자연스러운 포즈 전환을 기대할 수 있습니다.
이 플러그인 구성은 최신 언리얼 엔진의 핵심 기능을 모두 포함하고 있는 매우 진보된 형태입니다.

플러그인만으로도 공부할게 많다는 것을 알게 되네요. 거의 써본 적이 없는 플러그인들입니다. 최종 프로젝트에서 사용해보면 좋을 것 같은 것들이라 틈틈히 문서를 찾아보던가 해야 겠네요.


오류분석 튜토리얼

튜터님께서 메인메뉴 레벨에서 방생성 기능 동작하지 않는 것을 보여주셨습니다. 정확히는 방생성 버튼을 눌러도 아무런 반응이 없던 것인데요.

아마 클릭에 바인딩된 함수에 문제가 있거나 함수가 바인딩되지 않은 것으로 보입니다.
일단 어떤 위젯인지 알아봐야 하는데 해당 위젯이 무엇인지 알기위해 모든 위젯 클래스를 뒤지는 것은 비효율적이죠. 프로젝트가 커질수록 위젯의 수도 많아질 테니 더더욱이요.

문제가 발생한 위젯을 찾기 위해 위젯 리플렉터를 사용했습니다.

해당 버튼과 상호작용 시 상태가 바뀌는 위젯을 찾았고, 찾아낸 위젯을 클릭하니 콘텐츠 브라우저에서 해당 위젯 클래스가 있는 위치로 이동해준 덕분에 부모 클래스에 접근하기 쉬웠습니다.
내부의 코드를 보니 해당 버튼을 클릭 시 주소? 방생성에 필요한 정보를 입력하는 위젯이 보여야 하는데 Visilbity를 Hidden으로 설정하고 있었스빈다.

튜터님은 해당 부분은 Visible로 변경하여 문제를 해결했습니다.

당시에는 프로젝트의 압축해제가 진행중이서 따라하지 못했지만 내일 아침에는 해당 부분을 따라서 진행할 예정입니다.


위젯 리플렉터

위젯 리플렉터는 실시간으로 변화하는 위젯의 상태 정보를 표시하는 창입니다.

화면에 나타나는 위젯 하나당 한 줄이 추가됩니다. 위젯 내부에 표시되는 작은 위젯 컴포넌트들도 포함이고요.


서버에서 Slomo 호출?

강의 보면서 든 생각인데 Server에서 Slomo를 사용하면 적용이 되나요? 클라이언트에서는 무시당하는 것을 확인했습니다.

언리얼의 Slomo는 보통 월드의 Time Dilation을 바꾸는 개념이라고 합니다. 때문에 어느 월드에서 호출되었는 지가 중요하다고 합니다.

  • 서버 월드에서 실행 : 서버 기준 게임 속도가 느려질 수 있습니다.
  • 클라이언트에서만 실행 : 그 클라이언트 화면에서만 다르게 보일 수 있다고 합니다.
  • 멀티플레이에서는 동기화 의도 없이 쓰면 환란이 생기기 쉽다고 합니다.

클라이언트에서 Slomo를 호출했음에도 변화가 없던 이유는 시간 배율을 실제로 결정하는 권한이 서버 쪽에 있기 때문일 가능성이 커 보입니다.



Unreal Insight 보강 - 김조은 튜터님


Unreal Insight 열기

에디터 개인 설정 플레이 독립형 게임에서 플레이 추가 실행 옵션 파라미터에 -Log를 추가하면 PIE가 열리면서 같이 별개 개별 프로세스의 로그가 나옵니다.

verbose는 언리얼 엔진 내부의 것을 보여준다. 깊이 확인할 일이 없다면 Log에 체크하기.



Unreal Engine 고급 기술 활용


네비게이션은 내부에서 경로 탐색에 최소 비용으로 이동하는 경로를 계산합니다. NavigationModifier로 특정 영역의 비용을 변경할 수 있습니다.
매번 모든 네비게이션 영역을 계산하는 것은 낭비입니다. NavigationInvoker를 사용해 특정 네이게이션 메시만 활성화하는 것으로 최적화가 가능합니다.

내비게이션 영역 클래스를 사용하여 폴리곤 프로퍼티를 변경하고 이동 비용을 수정할 수 있습니다.
폴리곤 프로퍼티는 내비게이션 모디파이어 볼륨의 적절한 영역 클래스(Area Class) 에 의해 정의됩니다. 이 클래스는 내비게이션 메시에 가해지는 이펙트를 결정합니다. 내장 클래스를 사용하여 메시를 수정하거나 커스텀 구현을 생성할 수 있습니다.

사용 가능한 내비 모디파이어 볼륨 영역 클래스

영역 클래스설명
NavArea_Default볼륨 내 영역과 내비게이션 메시에 기본적으로 동일한 내비게이션 비용을 할당합니다.
NavArea_LowHeight에이전트가 지나가지 못하게 막는 낮은 높이가 있는 이동 조건에 일치하는 영역을 나타냅니다. 내비게이션 메시는 이 볼륨 내에 내비게이션 데이터를 생성하지 않습니다.
NavArea_Null볼륨 내의 빈 영역을 나타냅니다. 내비게이션 메시는 이 볼륨 내에 내비게이션 데이터를 생성하지 않습니다.
NavArea_Obstacle볼륨 내 영역에 높은 내비게이션 비용을 할당합니다.

런타임에서 에이전트 주변에 내비게이션 메시를 생성하는 블루프린트 액터 컴포넌트입니다. 내비게이션 인보커를 사용하면 내비게이션 메시를 에디터에서 빌드할 필요가 없어지며 런타임에서 생성되는 타일 수를 제한할 수 있습니다.

내비게이션 인보커는 에디터에서 내비게이션 메시를 빌드하는 것이 실용적이지 못한 대규모 레벨에 이상적아라 합니다.

프로젝트 세팅(Project Settings) -> 내비게이션 시스템(Navigation System) -> 내비게이션 생성(Generate Navigation Only Around Navigation Invokers) 체크박스를 활성화하고,
프로젝트 세팅(Project Settings) -> 내비게이션 메시(Navigation Mesh) -> 런타임(Runtime) -> Generation 드롭다운에서 Dynamic 선택해야사용할 수 있습니다.


테스트 화면

NavModier의 Area Class를 Obstacle로 설정한 뒤 0번 키를 누르면 AI가 이동하는 두 타겟 지점 사이를 가로막도록 배치했습니다.
NavModier의 Area Class를 Obstacle로 설정하면 해당 영억의 연산값? 코스트가 커져서 이동 로직에서 해당 위치로 이동하는 것을 피한다고 합니다.


profile
게임 개발 지망생입니다.

0개의 댓글