Youngki Jeong | Game Dev Lab
HomeProjectsEvidenceJourneyAbout
SearchGitHub글쓰기

Youngki Jeong | Game Dev Lab

Unreal C++ 게임개발 포트폴리오 & 개발 기록

Projects·Evidence·Journey·About·GitHub Portfolio·GitHub

빠른 검색

프로젝트, Evidence, 디버깅 노트, 학습 기록을 검색합니다.

← 목록으로
← 목록으로
RIT-B00

Unreal Gameplay Framework의 State와 책임을 따라간 프로젝트

2026년 9월 7일
·
JEONGYOUNGKI
Description

Lyra Starter Game Reference를 바탕으로 Unreal Gameplay Framework의 State, Owner, Lifetime을 따라간 프로젝트 소개

Project

RiteSeekers

ArticleType

Overview

SourceBoundary

My Extension

EvidenceLevel

Runtime

Priority

S++

Tags

GASUnrealGameplayFramework

ProofType

Source · Runtime

Audience

Recruiter

CareerTrack

Gameplay

목차

RIT-B00 | RiteSeekers — Unreal Gameplay Framework의 State와 책임을 따라간 프로젝트

프로젝트를 시작한 이유

RiteSeekers는 Unreal Engine의 Gameplay 구조를 실제 프로젝트 안에서 따라가며 이해하기 위해 시작한 개인 프로젝트입니다.

UE5.4, C++, Gameplay Ability System을 중심으로 Character, Ability, Equipment, Inventory, Combat이 어떻게 연결되는지를 확인했고, 필요한 부분은 직접 확장하면서 작업했습니다.

처음에는 눈에 보이는 결과를 만드는 데 더 집중했습니다.

캐릭터가 움직이고, 공격 Animation이 나오고, 적의 HP가 줄어들면 기능이 완성됐다고 생각하기 쉬웠습니다.

그런데 기능이 많아질수록 화면에 보이는 결과만 봐서는 전체 흐름을 이해하기 어려웠습니다.

공격 하나만 보더라도 실제로는 여러 시스템을 지나갑니다.

Text
Input
→ Ability
→ Animation
→ Trace
→ GameplayEffect
→ Attribute
→ Health

그래서 RiteSeekers에서는 기능 하나를 만들고 끝내기보다, 어디에서 시작해서 어떤 상태를 거쳐 실제 Gameplay 결과가 만들어지는지를 계속 따라가 봤습니다.


Project의 시작 설정부터 다시 봤다

처음에는 Content Browser에 있는 Experience나 PawnData부터 Gameplay 구성이 시작된다고 생각했습니다.

Source와 Project Settings를 다시 따라가 보니 그보다 앞에 Unreal Project 자체의 기본 설정이 있었습니다.

Maps & Modes에서는 기본 GameMode로 B_LyraGameMode를 사용하고 있고, PlayerController, GameState, PlayerState, HUD, Default Pawn Class 같은 Framework Class도 함께 확인할 수 있었습니다.

Map과 GameInstance 설정도 같은 곳에 있었습니다.

Text
Maps & Modes
→ Default GameMode
→ PlayerController / GameState / PlayerState
→ Default Map
→ GameInstance

여기서 한 가지 구분해서 본 것은 Project의 기본 Pawn 설정과 실제 RiteSeekers에서 사용할 Pawn 구성이 같다는 뜻은 아니라는 점이었습니다.

Lyra 계열에서는 이후 Experience와 PawnData를 거치면서 실제 플레이에 필요한 Pawn, AbilitySet, InputConfig, CameraMode가 다시 정해집니다.

제가 정리한 기준은 이 정도입니다.

Text
Maps & Modes
→ Project의 기본 Framework / Map
 
Experience / PawnData
→ 실제 플레이에 사용할 Gameplay 구성

Project Settings에서 확인한 것

Maps & Modes와 함께 본 것은 Asset Manager, Game Features, Gameplay Tags였습니다.

각 설정에서 제가 확인한 내용은 다음과 같습니다.

Text
Asset Manager
→ GameFeatureData / Experience 계열 Primary Asset
 
Game Features
→ LyraGameFeaturePolicy
 
Gameplay Tags
→ Ability / Combat / GameplayEvent / InputTag 등의 Tag 체계

Asset Manager에는 GameFeatureData, LyraExperienceDefinition, LyraUserFacingExperienceDefinition 같은 Primary Asset Type과 Experience를 찾을 경로가 설정되어 있었습니다.

Game Features에는 LyraGameFeaturePolicy가 Project Policy로 연결되어 있었고, Gameplay Tags에서는 Ability, Combat, GameplayEffect, GameplayEvent, InputTag처럼 여러 Gameplay 시스템에서 공통으로 사용하는 Tag들을 확인했습니다.

이걸 보고 나니 Experience나 GameplayTag를 각각 따로 떨어진 Asset으로 보기보다, 프로젝트가 Gameplay 구성을 준비하는 과정 안에서 같이 보게 됐습니다.

7._ProjectSettings_MapsAndModes.png.png

📸 Screenshot 1. Maps & Modes, Asset Manager, Game Features, Gameplay Tags에서 기본 Framework Class와 Map, Experience 계열 Primary Asset, LyraGameFeaturePolicy, GameplayTag 설정을 확인한 모습.


RiteCombatCore에서 Gameplay 기능이 연결됐다

Project Settings 다음에는 RiteCombatCore(GameFeatureData)를 따라가 봤습니다.

처음에는 GameFeatureData 안에 여러 Asset Reference가 모여 있는 것처럼 보였습니다.

그런데 Action을 하나씩 보니 Character, PlayerController, Input, UI처럼 실제 RiteSeekers에서 사용하는 기능이 여기에 연결되어 있었습니다.

제가 상위 흐름을 이해한 순서는 다음과 같습니다.

Text
Project Settings
→ GameFeature Policy
→ RiteCombatCore(GameFeatureData)
→ Experience
→ PawnData
→ Gameplay Runtime

RiteCombatCore의 Add Components에서는 Character와 PlayerController에 필요한 Component를 추가하도록 구성되어 있습니다.

Character 쪽에는 Equipment와 Inventory 관련 Component가 있고, PlayerController 쪽에는 Item 관리 Component가 연결되어 있었습니다.

RIT-B00_RiteCombatCore_AddComponents_Annotated.png

📸 Screenshot 2. RiteCombatCore(GameFeatureData)의 Add Components에서 Inventory / Equipment 관련 Component가 Character와 PlayerController에 연결된 설정.

이 화면을 보고 Inventory나 Equipment 기능이 Character Class 하나에 전부 들어 있는 것이 아니라, 필요한 Component를 GameFeature 쪽에서 연결하는 구조라는 점을 확인했습니다.

다만 이 Screenshot은 GameFeatureData에 어떤 Component가 설정되어 있는지를 보여주는 자료입니다.

각 Component가 Runtime에서 어떤 순서로 초기화되고 동작하는지는 Source와 Runtime을 따로 봐야 합니다.


Input과 UI도 같은 GameFeatureData에 들어 있었다

RiteCombatCore에는 Component만 있는 것이 아니었습니다.

Input과 UI를 연결하는 Action도 같이 들어 있습니다.

Text
RiteCombatCore
→ Add Input Mapping
→ IMC_RiteSeeker
 
RiteCombatCore
→ Add Widgets
→ W_RiteSeekerHUDLayout
→ UI.Layer.Game
RIT-B00_RiteCombatCore_InputUI_Annotated.png

📸 Screenshot 3. RiteCombatCore에서 IMC_RiteSeeker Input Mapping과 W_RiteSeekerHUDLayout을 연결한 GameFeature Action.

여기까지 따라가면서 RiteCombatCore를 단순한 Data Asset보다는 RiteSeekers에서 사용할 Component, Input, UI 구성을 한곳에 묶어놓은 GameFeatureData로 이해하게 됐습니다.

Input이 실제 Ability Activation까지 어떻게 이어지는지는 이후 Source를 따라가면서 따로 확인했습니다.


Gameplay Data도 용도별로 나뉘어 있었다

프로젝트에는 Experience와 PawnData 외에도 여러 Gameplay Data Asset이 있었습니다.

대표적으로:

Text
CharacterData_RiteCombatGame
ClassData_RiteCombatGame
ItemData_RiteCombatGame_RS

가 있습니다.

처음에는 Character, Class, Item 정보를 하나의 큰 Data Object에서 관리할 수도 있다고 생각했습니다.

현재 구조에서는 Character 구성, Class별 Ability와 초기 Item, ItemTemplate Registry가 서로 다른 Data로 나뉘어 있었습니다.

ClassData는 직업 선택과 Ability 구성으로 이어지고, ItemData는 ItemTemplate과 Runtime Item으로 이어집니다.

이 두 부분은 뒤에서 실제 Data Asset을 열어보면서 따로 정리했습니다.

B00에는 CharacterData Screenshot을 추가하지 않았습니다. Project Settings와 RiteCombatCore만으로도 이미 상위 구조가 충분히 보이고, Data Screenshot까지 넣으면 오히려 한 글 안에 너무 많은 내용을 보여주게 되기 때문입니다.


Experience에서 실제 Player 구성으로 내려갔다

Project Settings와 GameFeatureData를 지나면 Player 쪽 Gameplay 구성으로 이어집니다.

제가 Source를 따라가면서 자주 본 흐름은 다음과 같습니다.

Text
UserFacingExperience
→ Experience
→ PawnData
→ AbilitySet
→ ASC
→ Gameplay Runtime

Experience에서는 사용할 Pawn 구성을 결정하고, PawnData에는 Pawn Class, AbilitySet, InputConfig, TagRelationshipMapping, DefaultCameraMode 같은 정보가 연결되어 있습니다.

AbilitySet이 ASC에 Grant되면 그때부터 실제 Runtime Ability 상태가 만들어지고, Input이나 GameplayEvent를 통해 Ability가 실행될 수 있습니다.

처음에는 이런 Class 이름을 외우려고 했습니다.

지금은 Class 이름 자체보다 다음 단계로 어떤 정보가 넘어가고, 어느 순간 Runtime State가 만들어지는지를 더 많이 봅니다.

Experience와 PawnData의 Editor 설정은 B02에서 따로 정리했습니다.


Equipment도 Mesh만 바꾸는 기능은 아니었다

Item과 Equipment 역시 처음에는 화면부터 봤습니다.

Text
Item 장착
→ Weapon Mesh 변경

하지만 Gameplay 쪽까지 내려가면 상태가 더 이어집니다.

Text
Item
→ Equipment
→ Active Equip
→ AbilitySet
→ ASC AbilitySpec
→ Gameplay Ability

그래서 Item을 가지고 있다는 것, Equipment Slot에 들어 있다는 것, 현재 Active Equipment라는 것, 그리고 Ability가 ASC에 실제로 들어갔다는 것을 따로 보기 시작했습니다.

화면에 Sword가 보인다고 Sword Ability까지 정상적으로 들어왔다는 뜻은 아니었습니다.

이 흐름은 B05에서 ItemData, ItemTemplate, Fragment, Equipment, ASC까지 더 자세히 따라갑니다.


Combat에서는 공격과 추가 Rule을 나눴다

프로젝트 구조를 따라간 뒤 직접 확장한 부분 중 하나가 CombatAugment입니다.

처음에는 Blood나 Execution 같은 효과를 Melee Ability 안에서 처리하는 것도 생각할 수 있었습니다.

Text
Melee
→ Blood 처리
→ Execution 처리
→ 추가 Rule 처리

기능이 몇 개 없을 때는 가장 단순한 방식입니다.

하지만 Rule이 늘어나면 Melee가 실제 공격뿐 아니라 각 추가 효과의 조건까지 계속 알아야 했습니다.

그래서 실제 공격 결과와 그 뒤에 붙는 Combat Rule을 나눴습니다.

Text
Melee
→ Target / HitResult
→ GameplayEvent.Combat.HitConfirmed
 
HitConfirmed
→ Blood
→ Execution
→ 후속 Combat Rule

Melee에서는 실제 적중 결과까지만 만들고, Blood와 Execution은 그 결과를 받아 각자 필요한 조건을 판단하도록 구성했습니다.

이 부분은 B10에서 Grant부터 Trigger, Remove, Negative Test까지 Runtime으로 다시 확인했습니다.


화면에 보이는 상태와 Gameplay State도 따로 봤다

RiteSeekers를 진행하면서 계속 구분하게 된 것이 Visual과 Gameplay State였습니다.

Weapon을 예로 들면 여러 상태가 같이 변할 수 있습니다.

Text
Visual
→ Mesh
→ Animation
→ Camera
 
Gameplay
→ AbilitySet
→ AbilitySpec
→ Gameplay Ability

하지만 Weapon Mesh가 바뀌었다고 ASC의 Ability가 자동으로 바뀐 것은 아닙니다.

공격 Animation이 재생됐다고 Target에 실제 Hit가 발생한 것도 아닙니다.

처음에는 화면에서 결과가 정상적으로 보이는지가 가장 중요했습니다.

프로젝트가 커지면서 화면 결과와 실제 Runtime State를 같이 확인하게 됐습니다.


프로젝트를 진행하면서 보는 순서도 바뀌었다

Ability가 실행되지 않는다면 예전에는 Ability Class부터 열어보는 경우가 많았습니다.

지금은 먼저:

Text
Input
→ ASC
→ AbilitySpec
→ Activation

이 어디까지 이어졌는지를 봅니다.

장비가 바뀌었는데 Skill이 그대로라면:

Text
Equipment
→ Active Equip
→ AbilitySet
→ ASC AbilitySpec

을 봅니다.

Combat 결과가 이상하다면:

Text
Ability
→ HitResult
→ GameplayEffect
→ Damage
→ Health

순서로 실제 값이 어디까지 정상인지 확인합니다.

예전보다 기능 하나를 따로 보기보다, 그 기능이 프로젝트 안에서 어떤 흐름 안에 있는지부터 찾게 된 것이 가장 크게 달라진 부분입니다.


이후 글에서 따라간 내용

B00에서는 프로젝트의 가장 위쪽 구조부터 Runtime Gameplay까지 한 번에 훑었습니다.

이후 글에서는 각각의 흐름을 따로 떼어서 정리했습니다.

Text
B01
→ Reference 구조 분석과 적용·확장
 
B02
→ Experience에서 Gameplay Ready까지
 
B03
→ Job / Class가 Ability로 연결되는 흐름
 
B04
→ GAS Combat Flow와 Combat Rule 책임 분리
 
B05
→ Item과 Equipment가 Gameplay State로 이어지는 흐름
 
B06
→ Ability Activation이 끊긴 지점을 Runtime에서 확인한 과정
 
B07
→ Equipment 변경이 Ability State까지 이어지는지 확인한 과정
 
B08
→ 성능 문제를 코드보다 측정에서 먼저 보기 시작한 과정
 
B10
→ Relic 효과를 공격 코드와 분리한 과정
 
B11
→ 무기에 따라 Animation과 Camera 표현을 나눈 과정

각 글에서는 Class를 많이 나열하기보다 하나의 Gameplay 상태가 실제로 어디에서 시작하고 어디까지 이어지는지를 따라갔습니다.


정리

RiteSeekers를 시작했을 때 가장 큰 목표는 Unreal Gameplay Framework를 이해하는 것이었습니다.

처음에는 Experience나 Ability 같은 개별 기능부터 봤지만, 프로젝트를 계속 따라가면서 더 위쪽의 설정과 더 아래쪽의 Runtime 상태가 같이 보이기 시작했습니다.

Text
Maps & Modes
→ 기본 Framework / Map
 
↓
 
Asset Manager / Game Features / Gameplay Tags
→ Project 설정
 
↓
 
RiteCombatCore(GameFeatureData)
→ Component / Input / UI
 
↓
 
Experience / PawnData
→ Player Gameplay 구성
 
↓
 
AbilitySet / ASC
→ Runtime Ability State
 
↓
 
Equipment / Combat / Input
→ 실제 Gameplay
 
↓
 
Animation / Camera / UI
→ 플레이어에게 보이는 결과

처음에는 각 기능이 정상적으로 동작하는지를 가장 먼저 봤습니다.

지금은 그 기능이 어떤 설정에서 시작했고, 어떤 Data와 Runtime State를 거쳐 지금 보이는 결과까지 왔는지도 같이 봅니다.

Reference 구조를 따라가는 것에서 끝내지 않고, Combat Result와 CombatAugment처럼 현재 프로젝트에 필요한 부분을 직접 나누고 Runtime에서 확인해본 것도 RiteSeekers를 진행하면서 얻은 경험이었습니다.

빠른 검색

프로젝트, Evidence, 디버깅 노트, 학습 기록을 검색합니다.

목차