Skip to content

02_Gameplay_Architecture

github-actions[bot] edited this page Oct 19, 2026 · 3 revisions

02. Gameplay Architecture

Sonheim은 플레이어가 보유하는 데이터, 월드에서 실행되는 게임플레이, 클라이언트 UI의 역할을 분리합니다. 상태가 유지되어야 하는 범위에 따라 PlayerState·Pawn·Subsystem·ActorComponent를 선택하고, 화면에는 각 시스템의 변경 사항 또는 화면용으로 조합한 데이터를 전달합니다.

핵심 구조

구분 담당 실제 구현
플레이어별 기록·능력치 PlayerState의 컴포넌트 Inventory, StatBonus, PalInventory, MonsterDex, Quest
월드의 캐릭터 상태와 행동 Pawn / AAreaObject의 컴포넌트 이동·애니메이션·HP·Stamina·Condition·Skill
서로 다른 월드 오브젝트의 공통 동작 IInteractableInterface 아이템·보관함·제작대·던전 레버·입구
현재 던전 실행 UDungeonStageRuntimeSubsystem (UWorldSubsystem) 스테이지·이벤트·전환·실패·보상
여러 클라이언트가 볼 던전 상태 ASonheimGameState FDungeonStageRuntimeState 복제
에셋 로딩·저장된 진행 기록 UGameInstanceSubsystem DungeonAsset·DungeonProgress·MonsterDex·Quest
로컬 플레이어 화면 ULocalPlayerSubsystem GameUIManager·GameUIToast·DungeonUIRouter·Notice

데이터의 보관 위치, 변경 권한, 네트워크 전송 범위는 서로 다른 결정입니다. 예를 들어 Inventory 기록은 PlayerState의 컴포넌트에 있지만 실제 변경은 서버가 처리하고, 슬롯 상태는 소유 클라이언트에 복제합니다.

목차


전체 처리 구조

flowchart TB
    DEF["정의 데이터<br/>DataTable · DataAsset"]

    subgraph GAMEPLAY["서버 게임플레이"]
        PLAYER["PlayerState / ActorComponent<br/>Inventory · Stat · Pal · Quest · Dex"]
        PAWN["Pawn / AAreaObject<br/>Health · Skill · Condition · Movement"]
        DUNGEON["UDungeonStageRuntimeSubsystem<br/>스테이지·이벤트·전환"]
    end

    REP["캐릭터·플레이어 상태 복제<br/>Property / FastArray"]
    GAMESTATE["ASonheimGameState<br/>FDungeonStageRuntimeState"]
    PRESENT["UDungeonStagePresenter<br/>스냅샷 + UI 표시용 정의"]
    EVENT["상태 변경 Delegate / RepNotify"]
    VIEW["FDungeonStageViewData"]
    UI["UMG<br/>HUD · Inventory · Dungeon · Result"]
    NOTICE["UNoticeSubsystem<br/>Feed · Headline · Title"]

    DEF --> PLAYER
    DEF --> PAWN
    DEF --> DUNGEON
    PLAYER --> REP
    PAWN --> REP
    DUNGEON --> GAMESTATE
    REP --> EVENT --> UI
    GAMESTATE --> PRESENT --> VIEW --> UI
    DEF -. "던전 화면 설정 참조" .-> PRESENT
    GAMEPLAY -. "일회성 알림 전달" .-> NOTICE
    NOTICE --> UI
Loading

게임플레이 실행과 현재 상태 관리는 Actor·Component·Subsystem 안에서 이루어집니다. 복제가 필요한 상태만 클라이언트로 전달하며, UI가 모든 시스템의 실행 규칙을 직접 해석하지 않도록 표시 경로를 나눕니다.

위 그림은 주요 책임의 연결을 설명한 개념도입니다. 각 상태의 복제 조건과 화면별 갱신 방식은 아래에서 구분합니다.


객체 수명에 따른 역할 분리

PlayerState와 Pawn

ASonheimPlayerState는 플레이어의 보유 아이템, 스탯 보정, 보유 Pal, 도감·퀘스트 기록을 컴포넌트로 관리합니다.

// SonheimPlayerState.cpp — 생성자 발췌
m_InventoryComponent = CreateDefaultSubobject<UInventoryComponent>(TEXT("Inventory"));
m_StatBonusComponent = CreateDefaultSubobject<UStatBonusComponent>(TEXT("StatBonus"));
m_PalInventoryComponent = CreateDefaultSubobject<UPalInventoryComponent>(TEXT("PalInventory"));
m_MonsterDexComponent = CreateDefaultSubobject<UMonsterDexComponent>(TEXT("MonsterDex"));
m_QuestComponent = CreateDefaultSubobject<UQuestComponent>(TEXT("Quest"));

반면 ASonheimPlayer는 현재 조작하는 캐릭터의 이동·메시·애니메이션·전투 상태를 다룹니다. 공통 캐릭터 기반인 AAreaObject에는 UHealthComponent, UStaminaComponent, UConditionComponent, USonheimSkillComponent 등이 연결됩니다.

장비 변경을 예로 들면, 장비 및 스탯 보정 정보는 PlayerState에 두고, 계산된 공격력·최대 HP·이동 속도 등은 실제 Pawn에 적용합니다.

PlayerState / Inventory
   ↓ 장비 교체
StatBonusComponent · Skill Grant
   ↓
ASonheimPlayer
   ├─ 공격력·방어력 적용
   ├─ Health / CharacterMovement 반영
   └─ 무기 Mesh·HUD·사용 스킬 갱신

Inventory를 Pawn의 생성·파괴에 함께 묶지 않기 위한 구조입니다. 다만 PlayerState에 둔다고 디스크에 자동 저장되거나 모든 레벨 이동에서 상태가 보존되는 것은 아닙니다. 저장 여부는 별도 SaveGame 처리, Pawn과의 연결은 초기화·재연결 코드로 관리합니다.

WorldSubsystem·GameState·GameInstanceSubsystem

던전은 서로 다른 세 책임을 나눕니다.

  • UDungeonStageRuntimeSubsystem : UWorldSubsystem — 현재 월드에서 서버가 스테이지 진입, 이벤트 처리, 분기와 종료를 관리
  • ASonheimGameState — FDungeonStageRuntimeState를 복제해 참가 클라이언트가 같은 진행 상태를 확인하도록 전달
  • UDungeonAssetSubsystem / UDungeonProgressSubsystem : UGameInstanceSubsystem — 던전 에셋 로딩과 완료 기록의 SaveGame 관리

UDungeonStageRuntimeSubsystem::Publish로 반영된 상태는 ASonheimGameState::PublishDungeonStageState를 통해 복제됩니다. 서버의 실행 객체를 클라이언트에 그대로 복제하는 것이 아니라, 화면과 다른 월드 오브젝트에 필요한 현재 진행 정보를 스냅샷으로 전달합니다.

도감·퀘스트도 UMonsterDexSubsystem과 UQuestSubsystem이 정의 데이터를 조회하고 호스트 SaveGame을 관리하지만, 실제 플레이어별 진행 기록은 PlayerState의 Component가 관리합니다.

PlayerController와 LocalPlayerSubsystem

PlayerController는 로컬 입력과 UI 초기화, 서버·클라이언트 요청을 연결합니다. 화면 종류마다 입력 모드·커서 상태를 따로 관리하지 않도록 로컬 UI 관리 기능을 Subsystem으로 분리했습니다.

로컬 시스템 관리 내용
UGameUIManagerSubsystem 메뉴·인벤토리·도감·퀘스트 화면의 열림/닫힘, 레이어별 맨 위 화면의 입력 모드·커서
UDungeonUIRouterSubsystem 던전 HUD·결과 화면 생성·교체, ViewData 보관, 기존 HUD 숨김·복원
UNoticeSubsystem / UGameUIToastSubsystem 게임 알림 데이터 구성·채널 관리 / 슬롯별 표시 순서·대기 처리

로컬 플레이어의 메뉴·HUD·알림 관리는 이 계층에서 처리하고, 게임플레이 상태와 던전 진행 규칙은 각각 원본 시스템이 소유합니다.


컴포넌트와 인터페이스

ActorComponent — 상태와 기능을 조합

AAreaObject는 플레이어와 몬스터가 공유하는 캐릭터 기반 클래스입니다. Health·Stamina·Condition·Skill·Level과 이동·회전 관련 기능은 컴포넌트로 분리합니다.

AAreaObject : ACharacter
 ├─ UHealthComponent
 ├─ UStaminaComponent
 ├─ UConditionComponent
 ├─ ULevelComponent
 ├─ USonheimSkillComponent
 ├─ UMoveUtilComponent
 └─ URotateUtilComponent

외부 코드는 AAreaObject::DecreaseHP, AddCondition, CastSkill 같은 공통 API를 호출할 수 있습니다. 내부 상태 변경과 스킬 실행은 해당 컴포넌트와 스킬 로직에 위임합니다.

컴포넌트를 분리한 기준은 독립적으로 관리해야 할 상태가 있고, 플레이어·몬스터 등 여러 캐릭터가 같은 기능을 사용하는가입니다. 모든 로직을 컴포넌트로 나누지는 않았으며, 연동이 필요한 부분은 상위 Actor나 PlayerState가 연결합니다.

Interface — 서로 다른 오브젝트의 공통 상호작용

아이템, 보관함, 제작대, 던전 레버·입구는 클래스가 다르지만 IInteractableInterface의 공통 입력 흐름을 사용합니다.

flowchart TB
    INPUT["UInteractionComponent<br/>대상 탐색·입력·Hold"] --> IFACE["IInteractableInterface"]
    IFACE --> ITEM["아이템 획득"]
    IFACE --> CONTAINER["보관함 열기"]
    IFACE --> CRAFT["제작대 사용"]
    IFACE --> LEVER["던전 레버 작동"]
    IFACE --> ENTRANCE["던전 입구 사용"]
Loading

UInteractionComponent는 상호작용 가능한 대상을 찾고 입력·Hold 진행을 처리합니다. 각 대상은 표시할 안내, Hold 시간·취소 규칙, 실제 실행 동작을 인터페이스로 제공합니다.

새 오브젝트를 추가해도 플레이어 입력 코드에 오브젝트 종류별 분기를 늘리는 대신, 대상이 인터페이스를 구현하도록 했습니다. 자세한 판정·서버 실행은 06. World Interaction Systems에서 설명합니다.


정의 데이터·실행 상태·UI 표시 데이터

이 세 가지는 역할이 다릅니다.

구분 의미 실제 예
정의 데이터 스킬·던전 등 콘텐츠의 설정과 규칙 FSkillData, UDungeonDefinitionDataAsset
실행 상태 현재 게임에서 변하는 값 FSonheimSkillSpecItem, FDungeonStageRuntimeState
UI 표시 데이터 화면에 필요한 문구·수치·표시 상태로 변환한 값 FQuestView, FMonsterDexPageView, FDungeonStageViewData

스킬의 정의·상태·실행

FSkillData (DataTable)
 └─ 소모 비용·공격 범위·몽타주
          ↓
USonheimSkillComponent
 ├─ FSonheimSkillSpecItem : SkillId·bIsCasting·CooldownEndTime
 └─ UBaseSkill : 실제 스킬 실행 로직

스킬의 설정과 현재 사용·재사용 대기 상태, 실행 객체를 한 구조체에 섞지 않았습니다. FSonheimSkillSpecItem은 FastArray로 상태를 동기화하고, UBaseSkill은 스킬 실행을 담당합니다.

던전의 정의·진행·화면 표시

UDungeonDefinitionDataAsset은 스테이지·전환 규칙을 정의합니다. 서버 UDungeonStageRuntimeSubsystem은 실행 결과를 FDungeonStageRuntimeState로 발행하고, UDungeonStagePresenter는 화면 설정을 결합해 FDungeonStageViewData를 구성합니다. 전체 흐름은 위의 처리 구조도, UI 구현은 11. Client State Presentation에서 확인할 수 있습니다.

도감과 퀘스트도 정의와 기록을 각각 MonsterDexView::Build, QuestView::Build에서 결합합니다. 단일 컴포넌트의 HP나 인벤토리에는 별도 Presenter를 두지 않고 Delegate를 사용합니다.


상태 변경과 화면 갱신

데이터 갱신 경로 적용 화면
HP·인벤토리 UHealthComponent::OnHealthChanged, UInventoryComponent::OnInventoryChanged HUD·인벤토리
던전 진행 서버 Runtime → GameState Snapshot → Presenter → ViewData 던전 HUD·미니맵·결과
일회성 이벤트 UNoticeSubsystem → UGameUIToastSubsystem Feed·Headline·Title

던전 진행은 GameState Snapshot에서 읽지만 참가자의 HP는 각 UHealthComponent에서 구독합니다. 같은 HP를 스냅샷에 중복 보관하지 않습니다. 타이머는 서버 기준 시작·종료 시각으로 계산하므로 HUD를 다시 열어도 현재 진행 시간을 표시합니다.

알림은 현재 상태를 저장하는 수단이 아닙니다. 화면을 다시 열면 실제 HP·퀘스트·인벤토리 기록은 각 원본 컴포넌트에서 읽습니다.


던전에서 기존 시스템 재사용

Forgotten Ruins는 IInteractableInterface로 입구·레버 입력을 받고, 몬스터 처치·포획 결과를 던전 목표에 연결합니다. 보상은 기존 UInventoryComponent로 지급하며 보스의 피해·포획은 몬스터 공통 경로를 사용합니다.

레버는 상호작용 사실과 ID만 Runtime에 전달합니다. 실제 지름길 선택은 던전 Definition의 전환 규칙이 결정합니다. 09. Branching Dungeon Runtime에서 규칙과 이벤트 처리를 설명합니다.


선택 기준과 비용

설계 선택 적용한 이유 필요한 관리
PlayerState / Pawn 분리 보유 데이터와 현재 캐릭터의 수명 분리 Pawn 생성·교체 시 참조 재연결
ActorComponent HP·스킬 등 독립 기능의 공유와 조합 컴포넌트 초기화·의존 관계
Interface 다른 오브젝트에도 같은 입력·Hold 흐름 적용 인터페이스 규칙과 대상별 구현
WorldSubsystem + GameState 서버의 던전 실행과 클라이언트 상태 복제 분리 스냅샷 구성·복제 시점
정의 데이터 / 실행 상태 분리 같은 콘텐츠 정의로 여러 실행·플레이어 기록 관리 ID 대응과 상태 구조 관리
Presenter / ViewData 복합 상태를 UI에서 직접 해석하지 않음 화면용 데이터 변환 코드
LocalPlayer UI Subsystem 화면별 입력·수명 정책을 한곳에서 관리 화면과 게임플레이 간 입력 정책

단일 컴포넌트의 변경은 Delegate로 전달하고, 여러 출처의 데이터를 결합해야 하는 던전 화면에 ViewData를 구성했습니다. 상태의 소유 위치는 객체 수명과 복제 범위를 기준으로 정했습니다.

관련 코드 및 문서

Clone this wiki locally