언리얼 게임 데이터 관리 정리 (StatusComponent, PlayerState, GameInstance, DataTable)

언리얼 GameData 학습 노트. 강의 9.1/9.3/9.4 개념만. 데이터를 어디서 관리할지 헷갈릴 때 다시 보기.

 

데이터를 어디서 관리할 것인가 (가장 중요한 판단 기준)

이 챕터를 관통하는 핵심 결정. 데이터 성격에 따라 위치가 다름:

  • HP/MP처럼 캐릭터도 몬스터도 가지는 속성 → ActorComponent(StatusComponent). 누구에게나 붙일 수 있어야 하므로
  • KillCount/경험치처럼 플레이어만 가지는 특수 속성 → PlayerState
  • 게임 전역에서 하나만 존재해야 하는 데이터(밸런스 테이블 등) → GameInstance(싱글톤)

판단 질문: "이 데이터를 누가 가지는가, 라이프사이클이 어디까지인가."

ActorComponent로 스탯 분리

기존 컴포넌트들은 정해진 기능을 가져다 썼지만, ActorComponent를 상속해 직접 기능을 만들 수 있음. StatusComponent는 피격/스킬 등으로 스탯이 변하면 델리게이트로 알림 → UI 등이 느슨하게 결합.

설계 효과: 캐릭터 베이스에서 HP를 직접 들고 있던 것을 StatusComponent로 옮기면, 캐릭터/몬스터가 같은 컴포넌트를 공유. TakeDamage에서 StatusComponent->ApplyDamage 호출하고 IsDead로 분기. 죽으면 캐릭터는 콜리전/무브먼트 끄고, NPC는 추가로 AIController->EndAI(앞 챕터 함정과 동일).

치트시트:

  • Transient 키워드: CurrentHP처럼 개체마다 현재값이 다르고 직렬화에 포함될 필요 없는 속성에. 복붙(직렬화/역직렬화) 시 원본과 복사본이 같을 필요 없음
  • bWantsInitializeComponent: true여야 InitializeComponent()가 호출됨. 이건 액터의 PostInitializeComponents 직전에 불리는 컴포넌트 초기화 함수

PlayerState로 플레이어 전용 데이터 관리

플레이어 현재 상태 기록 클래스. HP/MP는 StatusComponent가 맡고(플레이어만의 개념이 아니므로), KillCount/경험치 같은 플레이어 특수 데이터를 PlayerState에.

연결: GameMode에 PlayerStateClass(클래스) 지정. NPC가 죽을 때 DamageCauser를 플레이어로 캐스팅 → 그 플레이어의 PlayerState를 얻어 AddCurrentKillCount. 값 변경 시 델리게이트 Broadcast로 UI에 전파.

GameInstance 싱글톤과 DataTable

데이터가 여러 개체에 흩어지면 동기화 문제(A는 10, B는 7). 게임 내 단 하나 보장이 싱글톤. 언리얼 싱글톤은 엔진 초기화~게임 종료까지 생존. 게임 전역 데이터도 같은 라이프사이클이어야 하므로 GameInstance에.

언리얼이 제공하는 싱글톤: GameInstance, AssetManager, GameMode/GameState, 프로젝트에 등록한 Game Singleton Class.

DataTable(csv) 흐름:

  • 기획의 엑셀은 .csv로 export. 에디터에서 import
  • import 시 FTableRowBase 상속 구조체가 필요. csv의 열 이름과 구조체 멤버 이름이 일치해야 함
  • import 시 Row Type으로 그 구조체 지정
  • 코드에서 FindRow<구조체>(키, "")로 행 조회

함정: csv 열 이름과 구조체 멤버 이름이 안 맞으면 import/조회가 깨짐. GameInstance Init에서 데이터 테이블 유효성(행 개수 등)을 check로 검증해두면 누락을 일찍 발견.

+ Recent posts